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
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.
Jim M. schrieb: > Woher zum Teufel sollen wir das wissen? Den Source Code haben wir nicht > vorliegen. Den Link hast du aber gecheckt oder?
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.
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.
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.
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 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.