struct geht verloren (Socket, Threads)
-
Ich weiß, dass es viel Quelltext ist und ich hab dazu noch wenig Angaben, wo genau der Fehler liegt - der Code is wahrscheinlich auch ein wenig unübersichtlich und zeigt, dass ich nicht der beste Programmierer bin - aber im thread waitforanswer wird der String richtig empfangen
Beim ersten mal geht auch alles super im command-Thread, aber wenn der Thread zum zweiten mal startet, ist der Pointer auf einmal fehlerhaft (also ich bekomme keinen Zugriffsfehler, aber auf einmal sind völlig komische Werte in dem struct (DATA) - der Socket hat viel zu viele Stellen, der string buffer ist "", der state ist -44 oder so was in der Richtung und das Handle isfree hat auch ne mehr, als eigenartige Adresse im Heap - zumindest lt. Debugger) - und ich finde den Fehler einfach nicht - wäre sehr dankbar über einen Tip.
Danke schon mal...#define maxHandle 2 #define exitH 0 #define sendH 1 typedef pair <WSAEVENT*, SOCKET> paar; struct sthreads { vector <paar> handles; unsigned __int16 ceil; HANDLE isfree; };void waitforanswer (void *threads) { std::auto_ptr <sthreads> D (static_cast <sthreads*> (threads)); unsigned __int32 z = D->ceil; SOCKET s = D->handles[z].second; WSAEventSelect (s, D->handles[z].first[sendH], FD_READ); WSAEVENT e[maxHandle]; e[exitH] = D->handles[z].first[exitH]; e[sendH] = D->handles[z].first[sendH]; SetEvent (D->isfree); data *DATA = new data; DATA->sock = s; DATA->isfree = CreateEvent (NULL, false, false, NULL); DATA->buffer = ""; DATA->state = state_empty; _beginthread (command, 0, (void *) DATA); SetEvent (DATA->isfree); char buf[l]; memset (buf, 0, l); signed __int32 E = 1; while ((E != 0) && (E != -1)) { E = WSAWaitForMultipleEvents (maxHandle, e, false, WSA_INFINITE, false); WSAResetEvent (e[E - WSA_WAIT_EVENT_0]); switch (E - WSA_WAIT_EVENT_0) { case exitH: _endthread (); break; case sendH: E = recv (s, buf, l-1, NULL); if (E < 1) { if (WSAGetLastError () == 10035) { E = -99; } } break; } if (E != -99) { WaitForSingleObject (DATA->isfree, INFINITE); while (E == WSAEMSGSIZE) { DATA->buffer += buf; memset(buf, 0, l); E = recv (s, buf, l-1, NULL); }; DATA->buffer += buf; _beginthread (command, 0, (void *) DATA); SetEvent (DATA->isfree); memset (buf, 0, l); } else { Sleep (100); } }; std::cout << (signed __int32) s << ": disconnect" << std::endl; CloseHandle (DATA->isfree); delete DATA; _endthread(); };struct data { SOCKET sock; std::string buffer; signed __int8 state; HANDLE isfree; };void command (void *DATA) { std::auto_ptr <data> D (static_cast <data*> (DATA)); WaitForSingleObject (D->isfree, INFINITE); if (!D->buffer.empty ()) { std::cout << (unsigned __int32) (D->sock) << " " << D->buffer << std::endl; } else { std::cout << (unsigned __int32) (D->sock) << ": connect" << std::endl; } std::string tosend = ""; //... if (!D->buffer.length ()) { tosend = "ichwerdegesendet"; D->state = state_hell; } else tosend = "1"; D->buffer = ""; if (tosend.length () > 1) { std::cout << (unsigned __int32) (D->sock) << " > " << tosend << std::endl; (void) send ((unsigned __int32) (D->sock), tosend.c_str() , tosend.length (), 0); } else if (tosend == "1") { SetEvent (D->isfree); _endthread (); } SetEvent (D->isfree);
-
Hallo unskilled,
ich hab den Quelltext nur überflogen, aber wenn ich das jetzt richtig
gesehen habe, übergibst du 2 mal das gleiche Objekt und wegen desstd::auto_ptr <data> D (static_cast <data*> (DATA));wird deine Struktur nach verlassen des 1. Methodenaufruf gelöscht.
Außerdem kannst du dich, da du einen neuen Thread startest nicht
darauf verlassen, dass der Thread nicht erst nach demdelete DATA;(was zwar dahinter steht aber wegen des neuen Thread unwesentlich)
auf das (nicht mehr vorhandene) Objekt zugreift.Ich hab jetzt nicht gekuckt, ob die Schleife "wegen der Logik" nicht
vorher verlassen werden kann. Aber ne potentielle Fehlerquelle.Gruß,
CSpille
-
Danke erst mal : >
CSpille schrieb:
übergibst du 2 mal das gleiche Objekt und wegen des
std::auto_ptr <data> D (static_cast <data*> (DATA));wird deine Struktur nach verlassen des 1. Methodenaufruf gelöscht.
Und das kann ich wie verhindern?
in dem ich jedes mal ((data*)DATA)->... schreibe oder gibts da auch noch ne bessere Variante?CSpille schrieb:
Außerdem kannst du dich, da du einen neuen Thread startest nicht darauf verlassen, dass der Thread nicht erst nach dem
delete DATA;(was zwar dahinter steht aber wegen des neuen Thread unwesentlich) auf das (nicht mehr vorhandene) Objekt zugreift.
Ja, das muss ich noch ändern, aber der Thread wurde bisher noch nicht so beendet - also ne potentielle Fehlerquelle ist es, aber in dem Fall war es nicht der Fehler, da ich in der Schleife bleibe...
Tom
//edit: ich hab jz jedes mal ((data*)DATA)-> bzw ((sthreads*)threads)-> geschrieben und es geht wieder einwandfrei : >
Danke noch mal
-
Hi unskilled,
warum castest du nicht einmal normal?
data* myData = static_cast <data*>(DATA);bzw:
data& myData = *static_cast <data*>(DATA);und greifst anschließend mit myData-> bzw. myData. über diesen Zeiger
bzw. Referenz zu?Gern geschehen...
Mir hat man hier auch schon oft genug geholfen

Gruß,
CSpille
-
l-1lol