multithreading - Pointer is deallocated shortly after declaration in multithread function -
i'm having weird problem in code of mine. variable seems fine after declaration corrupted right after , results in access violation (basically pointer still pointing @ same place memory seems unallocated). i'm pretty sure problem related multithreading have no idea since quite new multithreading.
here code :
#include "firewall.h" #include <ws2tcpip.h> firewall::firewall(void) { } firewall::~firewall(void) { } void firewall::parsefile(string filepath) { xmlnode xmainnode=xmlnode::openfilehelper(filepath.c_str(),"firewall"); // filtrage xmlnode nodefiltrage = xmainnode.getchildnode("filtrage"); xmlnode currentnode; for(int i=0; < nodefiltrage.nchildnode();i++) { currentnode = nodefiltrage.getchildnode(i); string nom = currentnode.getname(); if(nom == "permettre") mapfiltrage_.insert(pair<int,bool>(atoi(currentnode.getattribute().lpszvalue), true)); else if(nom == "bloquer") mapfiltrage_.insert(pair<int,bool>(atoi(currentnode.getattribute().lpszvalue), false)); } // redirection xmlnode noderedirection = xmainnode.getchildnode("redirection"); xmlnode currentsubnode; for(int = 0; < noderedirection.nchildnode(); i++) { currentnode = noderedirection.getchildnode(i); currentsubnode = currentnode.getchildnode("source"); sourcedestination source((string)currentsubnode.getattribute("adresse"), atoi(currentsubnode.getattribute("port"))); currentsubnode = currentnode.getchildnode("destination"); sourcedestination destination((string)currentsubnode.getattribute("adresse"), atoi(currentsubnode.getattribute("port"))); mapredirection_.insert(pair<sourcedestination, sourcedestination>(source,destination)); pair<sourcedestination, sourcedestination> test; } } void firewall::initialiser() { std::map<int, bool>::iterator iterfiltrage = mapfiltrage_.begin(); handle handlethread; std::string tempfiltrage = "localhost"; thread_arg arg; // parcours et lancement des connexions de filtrage while(iterfiltrage != mapfiltrage_.end()) { arg.port = (*iterfiltrage).first; arg.host = tempfiltrage; arg.objref = this; handlethread = createthread(null, 0, listenthread, &arg, 0, null); listethread_.push_back(handlethread); iterfiltrage++; } // parcours et lancement des connexions de redirection std::map<sourcedestination, sourcedestination>::iterator iterredirection = mapredirection_.begin(); while(iterredirection != mapredirection_.end()) { // Éviter la duplication inutile des sockets if(mapfiltrage_.find((*iterredirection).first.port()) == mapfiltrage_.end()) { arg.host = (*iterredirection).first.host(); arg.port = (*iterredirection).first.port(); arg.objref = this; handlethread = createthread(null, 0, listenthread, &arg, 0, null); listethread_.push_back(handlethread); } iterredirection++; } } dword winapi firewall::listenthread(lpvoid lpparam) { thread_arg* temp = (thread_arg*)lpparam; firewall* firewallref = temp->objref; return firewallref->runthread(lpparam); } dword firewall::runthread( lpvoid lpparam ) { thread_arg* infossocket = (thread_arg*)lpparam; // créer le socket et l'attacher à la source socket sock = socket(af_inet, sock_stream, 0); if(sock == invalid_socket) { cout << "erreur de creation de socket" << endl; return exit_failure; } //recuperation de l'adresse locale hostent *thishost; const char* test = infossocket->host.c_str(); thishost=gethostbyname(test); char* ip; ip=inet_ntoa(*(struct in_addr*) *thishost->h_addr_list); sockaddr_in sin; sin.sin_addr.s_addr = inet_addr(ip); sin.sin_family = af_inet; sin.sin_port = htons(infossocket->port); if(bind(sock, (sockaddr*)&sin, sizeof(sin)) == socket_error) { cout << "erreur de binding" << endl; return exit_failure; } // contexte du client sockaddr_in csin; socket csock; socklen_t crecsize = sizeof(csin); listesocket_.push_back(sock); listesocket_.push_back(csock); // Écouter sur le port if(listen(sock, 5) == socket_error) { cout << "erreur de listen" << endl; return exit_failure; } //csock = accept(sock, (sockaddr*)&csin, &crecsize); return exit_success; } void firewall::quitter() { // fermer les sockets vector<socket>::iterator iter1 = listesocket_.begin(); while(iter1 != listesocket_.end()) { closesocket((*iter1)); iter1++; } // fermer les threads vector<handle>::iterator iter2 = listethread_.begin(); while(iter2 != listethread_.end()) { terminatethread((*iter2), exit_success); closehandle((*iter2)); } }
thanks lot.
your problem in code:
thread_arg arg; loop(...) { arg = ...; handlethread = createthread(..., &arg, ...); }
every thread started here receives address of same thread_arg instance. then, starting next thread, again modify instance under feet of started thread. remedy, create structure holds necessary arguments (host, port, this) , handle thread. store structure in std::list , pass address of according element createthread().
there problem in code, should check returnvalues. it's nicer ask on code if know obvious errors have been detected. that, it's easiest use exceptions. after createthread(), should possibly beginthread() instead, add these lines:
if(handlethread == null) throw std::runtime_error("createthread() failed");
in second step, create dedicated exception class, derived runtime_error, holds win32 error code (see getlasterror()) , includes textual error description in exception message (see formatstring()). might sound lot of code nothing, write once , can reuse in many places.
lastly, quitter() has 2 problems. first infinite loop. assuming don't need handles after closing them, try instead:
for(; listethread_.empty(); listetread_.pop_back()) { terminatethread(listethread_.back(), exit_success); closehandle(listethread_.back()); }
you can write while-loop, too, prefer for-loop if number of iterations fixed. of course, still need check returnvalues of terminatethread() , closehandle(). second issue terminatethread() bad idea, because might terminating thread in middle of remains half-done. search web "terminatethread harmful". @ point here, can wait end using waitforsingleobject().
Comments
Post a Comment