Forum: PC-Programmierung Access Violation in DLL


von donvido (Gast)


Lesenswert?

Hallöchen,

Ich habe in dem Code an dem ich arbeite ein Problem dieser Art
https://blogs.msdn.microsoft.com/larryosterman/2004/04/22/when-global-destructors-bite/
entdeckt, dass sich bisher nicht bemerkbar gemacht hat.
Und zwar wird eine DLL erzeugt, die in unterschiedlichen Programmen 
eingebunden wird. Innerhalb der DLL wir ein XML mit Hilfe der ATL-Lib 
eingelesen. Jetzt ist erstmals dieses Problem aufgetreten, obwohl der 
Code so auch in den anderen Programmen verwendet wurde.

Meine Fragen:
1. Können Programme Access Violations unterdrücken, sodass kein Fehler 
produziert wird? Ich weiß dass das eine Programm in Delphi geschrieben 
ist (dort funktioniert es) und das andere scheint in Fortran geschrieben 
zu sein (hier lautet die Fehlerausgabe "forrtl: severe <157>: ...")

2. Ich habe in meinem Code das CoUninitialize(); auskommentiert und das 
Programm läuft durch. Muss ich schwerwiegende Probleme befürchten?
Ich habe von der ATL-Lib leider nicht viel Ahnung.

: Verschoben durch User
von Jim M. (turboj)


Lesenswert?

donvido schrieb:
> 1. Können Programme Access Violations unterdrücken, sodass kein Fehler
> produziert wird?

Nein.

Man kann höchstens mit
try {} catch {}

arbeiten, aber bei Acces Violations gibt es gerne mal Folgefehler.

donvido schrieb:
> Muss ich schwerwiegende Probleme befürchten?

Woher zum Teufel sollen wir das wissen? Den Source Code haben wir nicht 
vorliegen.

von donvido (Gast)


Lesenswert?

Jim M. schrieb:
> Woher zum Teufel sollen wir das wissen? Den Source Code haben wir nicht
> vorliegen.

Den Link hast du aber gecheckt oder?

von donvido (Gast)


Lesenswert?

Wie meinst du das mit den Folgefehlern?

von Nop (Gast)


Lesenswert?

donvido schrieb:
> Wie meinst du das mit den Folgefehlern?

Wenn ein Programm nicht das tun kann, was es soll, dann fehlen bestimmte 
Operationen. Sofern die wichtig waren, funktioniert das Programm danach 
nicht mehr wie beabsichtigt.

Wenn Du am Geldautomaten eine access violation bekommst und daher die 
Operation "Geld abheben" nicht sauber durchführen kannst, wird als 
Folgefehler davon Dein Einkauf spätestens an der Kasse auch scheitern.

von M.K. B. (mkbit)


Lesenswert?

Du sagst der Fehler tritt auf, wenn du CoUninitialize() auskommentierst.

Ohne deinen Code zu kennen würde ich mal darauf tippen, dass du in der 
DLL Speicher allozierst und diese nach dem Unload der DLL noch 
verwendest, aber die DLL ihren Speicher schon freigegeben hat.
Es reicht auch, wenn du aus der DLL ein Objekt als Pointer bekommst und 
es nicht oder nicht vor dem Unload der DLL zurückgibst.

von donvido (Gast)


Lesenswert?

M.K. B. schrieb:
> Du sagst der Fehler tritt auf, wenn du CoUninitialize()
> auskommentierst.

Dann tritt der Fehler nicht mehr auf.

Der  Code sieht ungefähr so aus
1
 void foo(char *inputFileName){
2
3
    CoInitialize(NULL);
4
    CComPtr<IXMLDOMDocument> iXMLDoc;
5
    iXMLDoc.CoCreateInstance(__uuidof(DOMDocument));
6
    iXMLDoc->load(CComVariant(inputFileName),&bSuccess);
7
    CComPtr<IXMLDOMElement> iRootElm;
8
    iXMLDoc->get_documentElement(&iRootElm);
9
    TElem eroot(iRootElm);
10
    
11
    do_something(); 
12
13
    CoUninitialize();
14
}

Ich habe wie gesagt von der ATL-Lib nich viel Ahnung.

von M.K. B. (mkbit)


Lesenswert?

Entschuldige den Schreibfehler, aber der Fehler ist genau der, den ich 
vermutet habe.
Ich habe mal nicht relevante Teile im folgende Code weggelassen.

Erklärung des Problems:
1
 void foo(char *inputFileName){
2
3
    CoInitialize(NULL);
4
    CComPtr<IXMLDOMDocument> iXMLDoc;
5
    // Im Heap der DLL wird Speicher für ein DOMDocument reserviert
6
    // und die Lebenszeit vom CComPtr hier kontrolliert
7
    iXMLDoc.CoCreateInstance(__uuidof(DOMDocument));
8
    // Gleiches wie oben für RootElement.
9
    CComPtr<IXMLDOMElement> iRootElm;
10
    iXMLDoc->get_documentElement(&iRootElm);
11
12
    do_something(); 
13
14
    // DLL wird freigegeben und damit wird auch der Heap
15
    // der DLL freigegeben.
16
    CoUninitialize();
17
18
// Hier werden die CComPtr zerstört und wollen Objekte aus der DLL freigeben,
19
// aber der DLL Heap wurde ja schon freigegeben und gehört nicht
20
// mehr zum Prozessspeicher => Access Violation
21
}

Lösung 1:
1
 void foo(char *inputFileName){
2
3
    CoInitialize(NULL);
4
    CComPtr<IXMLDOMDocument> iXMLDoc;
5
    iXMLDoc.CoCreateInstance(__uuidof(DOMDocument));
6
    CComPtr<IXMLDOMElement> iRootElm;
7
    iXMLDoc->get_documentElement(&iRootElm);
8
9
    do_something(); 
10
11
    iRootElm.Reset();
12
    iXMLDoc.Reset();    
13
14
    CoUninitialize();
15
}

Lösung 2:
1
 void foo(char *inputFileName){
2
3
    CoInitialize(NULL);
4
    {
5
        CComPtr<IXMLDOMDocument> iXMLDoc;
6
        iXMLDoc.CoCreateInstance(__uuidof(DOMDocument));
7
        CComPtr<IXMLDOMElement> iRootElm;
8
        iXMLDoc->get_documentElement(&iRootElm);
9
10
        do_something(); 
11
    } // CComPtr werden hier zerstört
12
13
    CoUninitialize();
14
}

von donvido (Gast)


Lesenswert?

Vielen Dank, das ist doch mal was.


Um nochmal auf meine 2. Frage zurückzukommen habe ich das ganze nochmal 
angepasst.
1
 void foo(char *inputFileName){
2
3
    CoInitialize(NULL);
4
    CComPtr<IXMLDOMDocument> iXMLDoc;
5
    // Im Heap der DLL wird Speicher für ein DOMDocument reserviert
6
    // und die Lebenszeit vom CComPtr hier kontrolliert
7
    iXMLDoc.CoCreateInstance(__uuidof(DOMDocument));
8
    // Gleiches wie oben für RootElement.
9
    CComPtr<IXMLDOMElement> iRootElm;
10
    iXMLDoc->get_documentElement(&iRootElm);
11
12
    do_something(); 
13
14
    // DLL wird nicht freigegeben und damit wird auch der Heap
15
    // der DLL nicht freigegeben.
16
    // CoUninitialize();
17
18
// Hier werden die CComPtr zerstört und wollen Objekte aus der DLL freigeben,
19
// der DLL Heap wurde noch nicht freigegeben und gehört noch
20
// zum Prozessspeicher => keine Access Violation
21
// Die DLL bleibt eingebunden bis zum Programmende
22
}

Die Funktion wird zur Programmlaufzeit nur ein einziges Mal aufgerufen. 
Die DLL würde also unnötigerweise eingebunden bleiben aber das sollte 
doch das einzige Problem sein oder? Damit bräuchte ich den Programmcode 
nämlich nur minimal anfassen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.