Access Violation in DLL

Gast #5377137
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.
Gast #5377319
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.
#5377731
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.
Gast #5377920
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.
#5377946
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
}
Gast #5378010
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren