Was kann die Ursache für segmentation fault mittels delete-Befehl in C++?
Ich habe ein Programm geschrieben, das ordnet ein neues Objekt der Klasse T, wie diese:
T* obj = new T(tid);
wo das tid ist ein int
Woanders in meinem code versuche ich das Objekt freigeben, das hab ich zugeteilt, die in einem Vektor, mit:
delete(myVec[i]);
dann:
myVec[i] = NULL;
Manchmal geht es ohne Fehler, und in einigen Fällen verursacht ein crash—ein segmentation fault.
Habe ich überprüft vor dem Aufruf löschen, und das Objekt ist da—ich habe Sie nicht gelöscht, es an anderer Stelle vor.
Was kann die Ursache für diesen Absturz?
Das ist mein code für das einfügen von Objekten vom Typ T auf den Vektor:
_myVec is global
int add() {
int tid = _myVec.size();
T* newT = new T (tid);
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(newT);
// _myVec.push_back(new T (tid));
return tid;
}
als es ist - das Programm manchmal abstürzt.
Wenn ich die Stelle des push_back Zeile mit dem Kommentar, und lasse den rest so wie es ist-es funktioniert.
aber wenn ich ersetzen Sie diesen code mit:
int add() {
int tid = _myVec.size();
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(new T (tid));
return tid;
}
stürzt es in einem anderen Stadium...
die newT-in der zweiten option ist unbenutzt und noch - änderungen, die den gesamten Prozess... was ist hier Los?
- Sind Sie sicher, dass die index-Punkt auf gültige array-Element?
- Um diese Frage zu beantworten, müssen wir die definition von
myVec
und wie Sie das einfügen von Elementen in es. - Dies könnte durch so ziemlich jede Art von Zeiger-Fehler oder buffer-overflow, so dass nur die Informationen, die Sie Gaben nicht helfen, das problem zu finden. Sie haben Zugriff auf ein tool wie Valgrind?
- Wenn das ist ein STL-Vektor verwenden
erase
oderstd::remove
statt ... müsste mehr relevanten code und oder callstack zu wissen, was verkehrt ist. - vielleicht wollen Sie auch zu prüfen, ob der Fehler Auftritt, in den Destruktor.
- Ich verstehe nicht, unabhängig von der seg. Fehler - was ist der Unterschied zwischen den drei Optionen mit push_back, die habe ich oben erwähnt, und warum jede von Ihnen die Ursache für das unterschiedliche Verhalten des Programms?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Segfaulting bedeuten, die versuchen zu manipulieren eine Speicheradresse, die nicht zugegriffen werden sollte, um die Anwendung.
Das bedeutet, dass dein problem kommen kann, von drei Fällen :
1) ist leicht zu überprüfen, so dass ich davon ausgehen tun Sie es bereits als zunichte machen Sie den Zeiger im vector. Wenn Sie das nicht tun prüft, dann tun Sie es, bevor die delete-Aufruf. Zeigen wird der Fall, wenn Sie versuchen, löschen Sie ein Objekt zweimal.
3) kann nicht passieren, wenn Sie set-NULL, um den Zeiger im vector.
2) könnte zu geschehen. In Sie Fall, bist du mit einem std::Vektor, richtig? Stellen Sie sicher, dass implizite Manipulationen der Vektor (wie Umverteilung der internen Puffer, wenn nicht groß genug, mehr) nicht beschädigt Ihrer Liste.
So, erste Prüfung, die Sie löschen NULL-Zeiger (beachten Sie, dass delete(NULL) wird nicht werfen! es ist der standard und gültiges Verhalten! ) - in Ihrem Fall sollten Sie nicht auf den Punkt kommen, um zu versuchen zu löschen(NULL).
Dann, wenn es nie passieren, überprüfen Sie, ob Sie nicht mit Ihrem vector füllen mit Zeiger deutete auf den Papierkorb. Zum Beispiel, stellen Sie sicher, Sie sind vertraut mit den [Remove-Erase-idiom][1].
Nun, dass Sie Hinzugefügt haben einige code, den ich denke ich kann das problem :
Bist du mit indice als ids.
Nun, hängt alles von der Weise, die Sie löschen Ihrer Objekte. (bitte zeigen Sie es für eine vollständige Antwort)
Wenn Sie nur tun, 1), dann sollte es sicher sein (wenn Sie nicht die Mühe machen, einen Vektor, der wächst und nie veröffentlicht und ids werden nicht wiederverwendet).
Wenn Sie 2. dann ist das alles falsch : jedes mal, wenn Sie entfernen ein Objekt aus einem Vektor, alle die das Objekt enthält immer noch nach dem entfernten Objekt-position verringert um eins. Macht alle gespeicherten id/index ungültig.
Stellen Sie sicher, dass Sie kohärent an diesem Punkt, es ist sicherlich eine Quelle von Fehlern.
delete (T*)0;
ist absolut sicher (oder so der standard verlangt), so gibt es keine Notwendigkeit zu prüfen vor dem Aufrufdelete
.dass segmentation fault, ist wahrscheinlich-und Speicher-Zugriffsverletzung. Einige Gründe
1) - Objekt bereits freigegeben ist. werden Sie sicher, dass Sie, dass array-position auf NULL nach dem löschen
2) Sie sind außerhalb der array-Grenzen
3) wenn Sie den Zugriff auf das array von mehreren threads stellen Sie sicher, dass Sie korrekt synchronisiert werden
Wenn Sie sich ganz sicher, dass Zeiger auf ein gültiges Objekt, und dass der Akt des löschen es zum Absturz, dann haben Sie die heap-Beschädigung.
Sollten Sie versuchen, mit einem ptr_vector, im Gegensatz zu deinem code, es ist garantiert die Ausnahme-sicher.
Hinweis: wenn Sie schreiben
delete
, du machst es falschKönnen Sie nicht sicher sein, dass das Objekt noch gültig ist: der Speicher, der durch das Objekt belegt ist nicht unbedingt gereinigt werden, und daher können Sie werden etwas sehen, das erscheint Ihr Objekt zu sein, aber es ist nicht mehr.
Können Sie eine Markierung, um sicher zu sein, dass das Objekt noch am Leben ist, und löschen Sie die Markierung in den Destruktor.
Diese Weise, überprüft die ersten 4 bytes in Ihrem Objekt, können Sie leicht überprüfen, ob Ihr Objekt abgeschlossen hat, seinem Leben oder nicht.