Speicherleck durch Call by reference und push_back
-
Hallo,
ich hoffe es ist das richtige forum und i.O. dass ich einen neuen Thread öffne...
Wenn nicht bitte nicht hauen.Ich bekomme ein Speicherleck beim Aufrufen einer Methode eines Objektes aus einem Thread:
bool database::getresultrow(string command, vector<string> & res) { unsigned int anzahl_felder; if (mysql_query (&mysql, command.c_str())) { cout<<stderr<<" - MySQL - getresultrow:query failed:"<< mysql_error (&mysql)<<endl; return false; } // recieve data from server mysql_res = mysql_store_result (&mysql); if (mysql_res == NULL) { cout<<stderr<<" - MySQL - getresultrow:Error recieving result:"<< mysql_error (&mysql)<<endl; return false; } anzahl_felder = mysql_num_fields (mysql_res); mysql_row = mysql_fetch_row (mysql_res); if (mysql_row==NULL) { cout<<"MySQL:Error getting resultrow - (really error?) getresultrow!"<<endl; return false; }; //die folgenden drei Zeilen verursachen das Speicherleck for(unsigned int i=0;i<anzahl_felder;i++) { res.push_back(mysql_row[i]); }; mysql_free_result (mysql_res); return true; };Übergeben wird ein String und ein Vektor in den das Ergebnis soll.
Aber wenn ich das Konsolenfenster beende, dann bekomme ich den folgenden Error:Die Anweisunng in "0x7c921e5a verweist auf Speicher in "0x00000004". Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden. Klicken Sie auf OK, um das Programm zu beenden"Aufgerufen wird diese Methode in einem Thread mit
bool object::loadfromdb(unsigned long idx) { vector <string> row; stringstream ss; ss<<"SELECT * FROM characters WHERE char_id="<<idx; bool tut=DB.getresultrow(ss.str(), row); if (tut==false) { cout<<"Error occured on database->getresultrow in player::loadfromdb-characters table"<<endl; return false; } else { /......Muss ich den Vektor manuell wieder löschen? Eigentlich müsste der Vektor doch auf dem Stack liegen und beim verlassen der Methode automatisch gelöscht werden, oder? (Oder waren beim Vektor die gepushten Sachen im Heap und nur die Veektorverwaltung im stack?)
Was mache ich diesmal wieder falsch?
OS: Win32, Compiler MinGW
Gruss
R
-
std::Robin schrieb:
Muss ich den Vektor manuell wieder löschen?
Nein, der ist auto und wird schon freigegeben.
Ich sehe in deinem Code nur ein potentielles Leck, und zwar bei mysql_res. Wenn mysql_row gleich NULL ist, wird mysql_free_result für mysql_res nicht aufgerufen. Da ich aber die mysql Funktionen nicht kenne, kann ich nicht beurteilen, wie relevant das ist. Die Fehlermeldung deutet aber auch eher auf einen ungültigen Zugriff hin (Pointerarithmetik + Indirektion mit einem Nullzeiger).
-
Hallo groovemaster, danke erstmal für deine Antwort.
Auch wenn ich das ganze MySQL Zeug auskommentiere und ich 1 mal etwas per push_back auf res packe kommt schon der o.g. Fehler.Es muss also irgenwas mit dem Container an sich oder dem Call by Reference zu tun haben. (glaub ich zumindest)
Was mich stutzig stimmt ist die Tatsache, dass wenn ich die Methode aus der main() aufrufe kein Speicherleck entsteht, sondern nur aus threads heraus...
Ich weiss wirklich nicht mehr weiter, insbesondere da die Funktion augenscheinlich genauso arbeitet wie sie soll.
Sollte ich vielleicht row mal volatile setzen?
Gruss
R
-
std::Robin schrieb:
Auch wenn ich das ganze MySQL Zeug auskommentiere und ich 1 mal etwas per push_back auf res packe kommt schon der o.g. Fehler.
Es muss also irgenwas mit dem Container an sich oder dem Call by Reference zu tun haben. (glaub ich zumindest)
Ich glaube eher, dass der Fehler durch etwas ganz anderes provoziert wird. Denn es ist erstmal nicht davon auszugehen, dass der Container fehlerhaft arbeitet. Und am Call by-reference liegt's mit Sicherheit auch nicht.
std::Robin schrieb:
Was mich stutzig stimmt ist die Tatsache, dass wenn ich die Methode aus der main() aufrufe kein Speicherleck entsteht, sondern nur aus threads heraus...
Evtl. Synchronisationsprobleme? Dh, du benutzt im Thread irgendwas, was in einem anderen Thread initialisiert wird. Zu diesem Zeitpunkt aber noch uninitialisiert wird. Btw, wie kommst du eigentlich darauf, dass der Fehler an besagter Stelle liegt? Reine Spekulation? Oder hast du irgendwelche konkreten Hinweise?
std::Robin schrieb:
Sollte ich vielleicht row mal volatile setzen?
Du meinst das row in object::loadfromdb? Nein, das würde nix bringen, da row funktionslokal ist und von aussen sowieso nicht verändert werden kann.
Also wie gesagt, ich kann in deinem Code erstmal nichts erkennen, was auf diesen Fehler hindeutet. Das muss aber nicht heissen, dass er dort nicht ist. Ich kenne wie gesagt die mysql Funktionen nicht. Dennoch würde ich auf eine andere Stelle als Fehlerursache tippen. Ich kann dir jetzt eigentlich nur den Tipp geben, mit Hilfe des Debuggers die betreffende Fehlerstelle (in der Meldung steht ja die Adresse) zurückzuverfolgen. Mittels Call Stack sollte das eigentlich kein Problem sein. Allerdings benutze ich für sowas VC, da dort ein richtig guter Debugger dabei ist. Wie ich sehe, benutzt du aber MinGW und unter Windows gibts afaik kein vernünftiges Frontend für GDB. Nur als Hinweis.