Segmentation fault in Mysql-ResultSet-Schleife
-
Hallo liebes Forum.
Aus einem mir nicht ersichtlichen Grund bekomme ich in einer while-Schleife in der ich die einzelnen Datensätze abwackel ein Segmentation fault. Der Debugger sagt, der Fehler kommt beim verlassen der Schleife, allerdings versteh ich das nicht. Wenn ich versuche den C_String nach jedem Schleifen Durchgang zulöschen kommt dasselbe.void enter(int d) //Funktion für neue Clients { sql::Driver *driver; //MySQL-Driver sql::Connection *con; //MySQL-Verbindug sql::Statement *stmt; //MySQL-Abfrage sql::ResultSet *res; //MySQL-Ergebnis driver = get_driver_instance(); con = driver->connect("tcp://192.168.0.4:3306","web","Sommer02"); con->setSchema("Chat"); stmt = con->createStatement(); std::string flick; //String zum zusammenflicken char* buf; //C_String fürs das Versenden an Client res = stmt->executeQuery("SELECT * FROM Messages WHERE M_zeit LIKE concat(CURDATE(),'%')"); while(res->next()) { if(connections[d].sock >= 0) { flick = res->getString("M_zeit") + " | " + res->getString("M_name") + ": " + res->getString("M_msg") + "\n"; buf = new char[flick.size()]; for(int i = 0; i<flick.size();i++) { buf[i] = flick[i]; } buf[flick.size()]='\0'; send(connections[d].sock,&buf[0],flick.size(),0); } } //Hier kommt der Segmentation Fault }
-
Du weisst dass std::string die Methode c_str() hat?!
-
ja das Problem dabei ist das dann const char* zurückgeliefert wird und mit strcpy wollte ich nicht arbeiten, das soll nicht so sicher sein.
-
Wenn du ein Array für n Elemente erstellst, welchen Index hat dann das letzte Element?
edit:
luggas schrieb:
ja das Problem dabei ist das dann const char* zurückgeliefert wird und mit strcpy wollte ich nicht arbeiten, das soll nicht so sicher sein.
lol - strcpy ist zu unsicher, aber mit dynamischen Arrays arbeiten
-
na der letzte Index ist flick.size()-1 oder etwa nicht?
-
luggas schrieb:
na der letzte Index ist flick.size()-1 oder etwa nicht?
stimmt. und mit diesem Wissen solltest du nochmal kritisch deinen Code betrachten.
übrigens fehlt das delete[] zu deinem new.
-
also mit dem Index müsste es soweit hinhauen, denn wenn ich die Bedingung der for-Schleife auf i<flick.size()-1 setze schneidet er mit das '\n' weg.
Was das delete[] buf angeht, da bringt er mir einen Fehlerfree(): invalid next size (fast)dann kommen ein haufen hexadezimale Adressbereiche und zum Schluss steht da das er abbgebrochen hat
Program received signal SIGABRT in __kernel_vsyscall()Ich denke das hängt irgendwie mit der Neualloziierung des C_Strings zusammen
edit:
ok strcpy würde gehen, aber ist doch letzlich egal ob ich das selber mache oder ob das strcpy macht beides gleich oder arbeitet strcpy anders?
-
luggas schrieb:
also mit dem Index müsste es soweit hinhauen, denn wenn ich die Bedingung der for-Schleife auf i<flick.size()-1 setze schneidet er mit das '\n' weg.
ich rede auch nicht von der Schleife.
luggas schrieb:
Was das delete[] buf angeht, da bringt er mir einen Fehler
wo hast du das denn eingefügt?
-
oh jetzt seh ichs
buf[flick.size()] = '\0'muss
buf[flick.size()-1] = '\0'heißen
ehm und zwar unter send einfach
delete[] buf;
-
es ist so unfassbar dieser Index war das Problem und deswegen ging auch delete[] nicht weil der ein Element dealloziieren wollte, welches garnicht da war
Danke sehr

-
...
-
das ist der MySQL-Connector
-
luggas schrieb:
buf[flick.size()-1] = '\0'heißen
Wenn du das letzte Zeichen im String nicht benötigst ...
-
ich habs jetzt andersrum
while(res->next()) { if(connections[d].sock >= 0) { flick = res->getString("M_zeit") + " | " + res->getString("M_name") + ": " + res->getString("M_msg") + "\n"; buf = new char[flick.size()+1]; for(int i = 0; i<flick.size();i++) { buf[i] = flick.at(i); } buf[flick.size()]='\0'; send(connections[d].sock,&buf[0],flick.size(),0); delete[] buf; } }Ausserdem brauch ich nochmal Hilfe.
Dieser Thread soll durchweg Datenbankabfragen machen und wenn etwas verändert wird oder hinzukommt an alle Clients verschicken. Allerdings versendet er die Daten nicht kommplett, und kratz dann ab mit der Meldung out of memory.void* brd_cst(void*) { try { sql::Driver *driver; //MySQL-Driver sql::Connection *con; //MySQL-Verbindug sql::Statement *stmt; //MySQL-Abfrage sql::ResultSet *res; //MySQL-Ergebnis //Verbindung herstellen zu MySQL-Datenbank driver = get_driver_instance(); con = driver->connect("tcp://192.168.0.4:3306","web","Sommer02"); con->setSchema("Chat"); stmt = con->createStatement(); std::string flick; char* buf; std::vector<std::string> result_old; res = stmt->executeQuery("SELECT * FROM Messages WHERE M_zeit LIKE concat(CURDATE(),'%')"); while(res->next()) { result_old.push_back(res->getString("M_ID")); } int i; while(true) { i = 0; res = stmt->executeQuery("SELECT * FROM Messages WHERE M_zeit LIKE concat(CURDATE(),'%')"); while(res->next()) //Datensätze abwackeln { if(i > result_old.size()-1) //Wenn die alten Datensätze weniger waren { pthread_mutex_lock(&mutex); for(int k = 0; k<MAX;k++) //Senden der Ergebnisse | alle Connections durchgehen { if(connections[k].sock >= 0) //Wenn Verbindung { flick = res->getString("M_zeit") + " | " + res->getString("M_name") + ": " + res->getString("M_msg") + "\n"; buf = new char[flick.size()+1]; for(int j = 0; i<flick.size();i++) { buf[j] = flick.at(j); //An dieser Stelle schreibt er komischer Weiße nur das erste Glied auf buf } buf[flick.size()]='\0'; printf("%s",buf);fflush(stdout); send(connections[k].sock,&buf[0],flick.size(),0); delete[] buf; } } pthread_mutex_unlock(&mutex); result_old.push_back(res->getString("M_ID")); //alte Datensätze aufrischen } else if(res->getString("M_ID").compare(result_old[i]) != 0) //Wenn Datensatz unterschiedlich { pthread_mutex_lock(&mutex); for(int k = 0; k<MAX;k++) //Senden der Ergebnisse | alle Connections durchgehen { if(connections[k].sock >= 0) //Wenn Verbindung { flick = res->getString("M_zeit") + " | " + res->getString("M_name") + ": " + res->getString("M_msg") + "\n"; buf = new char[flick.size()+1]; for(int j = 0; i<flick.size();i++) { buf[j] = flick.at(j); } buf[flick.size()]='\0'; printf("%s+L",buf);fflush(stdout); send(connections[k].sock,&buf[0],flick.size(),0); delete[] buf; } } pthread_mutex_unlock(&mutex); result_old[i] = res->getString("M_ID"); //alten Datensatze aufrischen } i++; } } delete res; delete stmt; delete con; } catch(sql::SQLException &e) { printf("%s\n",e.what()); } }
-
also das Problem mit dem String hab ich selbst gefunden hab mich in der for-Schleife vertippt, aber das out of Memory bekom ich nicht weg
-
Du machst mit Exceptions rum und wartest sogar auf diese, benutzt aber fleissig wo es nur geht new ??
Das widerspricht sich und ist total grob falsch.
Ich kenne die SQL-Wrapper nicht und hab mir deinen Code auch nicht wirklich angesehen. Aber was dir apssieren könnte ist, dass bei dir fleissig SQL-Exceptions kommen, diese werden gefangen (alles kein Problem), aber du baust dir pro Funktionsaufruf hier ein Speicherloch welches nicht gelöscht wird. Das passiert dann pro Sekunde paar 100mal und zack ist dein RAM voll und dein Betriebssystem mag dir keinen Speicher mehr geben...
Guck doch wenigstens mal parallel den Taskmanager dabei an...
(Unter Linux gibt es ja sicher was ähnliches)
-
musst du res, con und stmt wirklich manuell freigeben?
-
ja das steht so in dem Manual.
BTW hab ich es gelöst indem ich nach jedem Schleifen Durchlauf res mit delete freigebe und erneut am anfang deklariere.
Die Sache mit den Exceptions ist ein guter Hinweis. Meinst du ich sollte diese nur fangen wenn sie auch gewurfen werden können? Die endlos Schleife ist allerdings gewollt.
-
luggas schrieb:
es ist so unfassbar dieser Index war das Problem
Du provozierst solche Fehler geradezu, wenn du ständig auf tiefer Abstraktionsebene entwickelst.
Statt statischen Arrays, nimm
std::array(hat Index-Checks im Debug-Modus, neben vielen sonstigen Vorteilen). Stattnew[]unddelete[], nimmstd::vector. Stattchar*, nimmstd::string. Stattnewunddelete, nimm automatische Objekte oderstd::unique_ptr. Diese Techniken sind allesamt sicherer und einfacher zu verwenden.Kurz: Benutze RAII. Dann löst du auch schön das von Skym0sh0 angesprochene Problem der Exceptionsicherheit.
-
Versteh ich das richtig mit exception-sicherheit meint ihr, das der code der gefahr ausläuft objekte nicht zu dealloziieren, wenn er eine exception wirft?
Mit raii hab ich noch nicht gearbeitet, aber ich versuch es mal zu implementieren. Danke euch.
-
luggas schrieb:
Versteh ich das richtig mit exception-sicherheit meint ihr, das der code der gefahr ausläuft objekte nicht zu dealloziieren, wenn er eine exception wirft?
Ja. Denn der aktuelle Programmfluss wird ja sofort unterbrochen und es wird zum nächsten passenden catch gesprungen. Und in diesem hast du ja kein delete[]...
int main() { __int64 count = 0; try { char * buf; while ( 1 ) { buf = new char[100]; std::memset(buf, ' ', 100); count++; } } catch (std::exception & e) { std::cout << e.what() << std::endl; std::cout << "Counts: " << count << std::endl; std::cin.get(); return -1; } }Diesen Code hab ich grad mal bei mir laufen lassen, der kackt nach etwa 13-15 Millionen Durchläufen ab. Dauert keine 20 Sekunden. So kannst du dir das vorstellen. (Das try-catch ist auch nur dafür da, dass man überhaupt was sieht. Kannst ja selbst mal ausführen.
luggas schrieb:
Mit raii hab ich noch nicht gearbeitet, aber ich versuch es mal zu implementieren. Danke euch.
RAII ist so wichtig, grundlegend und mächtig, dass es wehtut wenn man es nicht verwendet... Nachholen Kollege!