Was kann die Ursache VTable-Zeiger, 0xdddddddd in Win32-debug-build?
Ich bin debugging ein Mangel, und haben es eingeengt zu den vtable-Zeiger für ein Objekt 0xdddddddd
. Diese Antwort zeigt an, dass die Win32 debug-builds wird in der Regel festgelegt, Toten Speicher, oder Speicher, die gelöscht wurde, um diesen besonderen Wert.
Beachten Sie, dass die Zeiger selbst sieht gültig, es ist nur die vtable-Zeiger, dass ist 0xdddddddd
.
Hier ist ein code-snippet:
std::list<IMyObject*>::const_iterator it;
for (it = myObjects.begin(); it != myObjects.end(); ++it)
{
IMyObject* pMyObject = *it;
if (pMyObject == 0)
continue;
pMyObject->someMethod(); //Access violation
}
Wenn ich Pause auf der Linie der Zugriffsverletzung und Uhr pMyObject
kann ich sehen, dass pMyObject
selbst hat eine gültige Adresse ( 0x08ede388
), aber die __vfptr
Mitglied ist ungültig (0xdddddddd
).
Einige Hinweise:
- Es ist ein single-threaded-Anwendung, so ist dies wahrscheinlich nicht eine race-condition oder mutex-Problem.
- Dort nicht erscheinen zu sein irgendwelche offensichtlichen Probleme, wie löschen von dem Objekt, das sich weiter oben auf dem Aufruf-stack) vor dem Zugriff auf Sie.
- Dieses Problem scheint nur reproduzierbar auf Windows 2008 server, aber nicht auf Windows 7.
Anregungen dazu, wie Sie Debuggen weiter?
- Das sieht aus wie ein klassischer Fall von jemandem, löschen Sie das Objekt, nachdem Sie die Zeiger in die Liste ein. Sind Sie sicher, dass das nicht der Fall ist (es könnte gelöscht werden, eine andere Funktion, die nach dem Befüllen der Liste, so dass Sie einen Blick auf den call-stack kann nicht viel helfen). Die einfachste Sache zu versuchen ist, setzen Sie einen Haltepunkt in der Destruktor
IMyObject
und jemanden sehen, ist das löschen des Objekts.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie mit den Zeiger, nachdem es freigegeben wurde. Holen Sie sich einen stack-trace aus einem Haltepunkt im Destruktor, um zu sehen, was es zu löschen. Oder besser noch, verwenden Sie shared_ptr<> um das problem zu vermeiden.
QSharedPointer
könnte ein guter Kandidat).Wenn Sie das Programm starten, setzen Sie einen break-Punkt, an dem Sie das Objekt erstellen. Dann fügen Sie einen Speicher-breakpunkt. Dieser wird ausgelöst, wenn Sie überschreiben oder löschen Sie den Speicher. Gut, oder ändern Sie es in irgendeiner Weise.
Ihrem Objekt Aussehen wird korrekt, wenn der Speicher noch nicht überschrieben, aber Ihr vtable kann nicht sein, je nach compiler Besonderheiten.
Könnte es auch sein, ein Größe-problem, wenn Sie mit Vererbung. Wenn Sie mit jeder Art von Eimer-Speicher oder speichern von Objekten, die durch nichts, aber die Zeiger.
Wenn pMyObject->someMethod() endet schließlich in einer änderung des myObjects Liste wird die Gültigkeit der aktuellen Iteratoren.
Zusätzlich, wenn der Zeiger die Daten bereits gelöscht, dies löst das gleiche Problem.
Okay, wow, also habe ich die Programmierung in c++ für Jahre und nie entdeckt bis jetzt... Es gibt tatsächlich Magische Zahl/Magisches debug-Werte, dass kann man nachschlagen, um zu sehen, was Los ist mit Ihren raw-Pointer beim Debuggen!
Siehe hier: In Visual Studio C++, was sind die memory-allocation-Darstellungen?
und hier: https://en.wikipedia.org/wiki/Magic_number_(Programmierung)#Magic_debug_values