Ich habe einen Absturz, der mich verwirrt und den ich bis jetzt für unmöglich gehalten habe, konsistent zu reproduzieren. Der Code wird mit Visual Studio erstellt 2008.C++ Programmabsturz (C0000005 Zugriffsverletzung) bei Aufruf
Die (vereinfachte, natürlich) Quellcode sieht wie folgt aus:
class AbstractParentClass
{
private:
/* data members */
public:
AbstractParentClass();
/*
virtual functions ...
*/
};
class ChildClass : public AbstractParentClass
{
private:
/* data members */
public:
ChildClass();
/*
overridden/implemented virtual functions ...
*/
};
void DifferentClass::func(const char ** strs)
{
ChildClass child_class;
int i = 0;
[...]
}
Die Demontage von der Crash-Dump wie folgt aussieht:
Library!DifferentClass::func:
612cab20 83ec58 sub esp,58h
612cab23 56 push esi
612cab24 57 push edi
612cab25 8bf9 mov edi,ecx
612cab27 8d4c2420 lea ecx,[esp+20h]
612cab2b e8e053403f call a06cff10
612cab30 8b742464 mov esi,dword ptr [esp+64h]
[...]
Ordnen Sie die Quelle von func() gegen die Demontage an, es sieht aus wie folgt:
In einem erfolgreichen Lauf (andere Maschine, obwohl auf der gleichen Maschine, der Absturz ist nicht zuverlässig reproduzierbar), der einzige Unterschied in der Disassemblierung ist die Aufrufanweisung, die korrekt auf die Adresse des Standardkonstruktors von ChildClass Mapping, dies wie:
00404e8b call ChildClass::ChildClass (40a3d0h)
statt wie:
612cab2b call a06cff10
so bei dem Absturz läuft, dass a06cff10 Adresse, die als Call-Anweisung des Parameter dient dazu, zu sein scheint kommend wer weiß, wo und ist nicht auf etwas Bestimmtes abgebildet. Und so, wie zu erwarten, Zugang versucht, die Adresse (an die Child Standardkonstruktors zu erhalten) wird, was zu einer Zugriffsverletzung:
EXCEPTION_RECORD: 0012f688 -- (.exr 0x12f688)
ExceptionAddress: a06cff10
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: a06cff10
Attempt to read from address a06cff10
Jeder Versuch, an dieser Adresse in dem Crash-Dump zu sehen gibt in der Tat, dass die Adresse aus ist Grenzen für den Prozess.
UPDATE: Also nach dem Lesen der Antwort unten von zvrba und schaut es weiter an, scheint der problematische Aufruf der erste von einem Dutzend Funktionsaufrufe in einer statischen Bibliothek zu sein (die wiederum von einer DLL geladen wird) alle haben einen falschen Funktionsoffset. Sie sind nicht alle Funktionen in derselben Klasse. Es gibt drei oder vier verschiedene Klassen mit betroffenen Funktionen, obwohl alle Klassen (die aufgerufen werden und aufgerufen werden) in derselben statischen Bibliothek existieren. In diesem ersten Aufruf, der Dinge abstürzte, war der Befehl e8e053403f und der 3F4053E0-Offset in diesem Befehl sollte einen Offset von nur 53E0 haben. Alle anderen Instanzen haben das gleiche Offset-Problem. Der Offset in der Anweisung ist 3F40XXXX, wenn er nur XXXX sein sollte. Der extra 3F400000 schickt natürlich Dinge in Never Never Land. Bisher habe ich kein Muster aufgegriffen, hinsichtlich welcher Funktionsadressen innerhalb der Demontage gültig sind und welche nicht. Eine Memberfunktion von DifferentClass in der Bibliothek hat alle Aufrufe von ChildClass als fehlerhaft, während eine andere Memberfunktion von DifferentClass einen anderen Aufruf in ChildClass hat.
Hat jemand da draußen so etwas gesehen/irgendwelche Gedanken über mögliche Ursachen davon?
Vermissen Sie die Initialisierung einer Klassenmitgliedsvariablen? – GWW
Ist es möglich, dass etwas 3f schreibt, um zur Laufzeit 612cab2f zu adressieren? – TonyK
Schalten Sie die Warnstufe hoch: W4 auf VS oder -Wall -Wextra -pedantisch auf gcc dann stellen Sie sicher, dass es mit 0 Warnungen kompiliert. –