2009-05-27 10 views
0

Ich habe eine C++ DLL mit Code wie folgt:Ist es für einen Bibliotheksbenutzer möglich, C++ - Ausnahmen zu umgehen?

LogMessage("Hello world"); 
try { 
    throw new int; 
} catch(int* e) { 
    LogMessage("Caught exception"); 
    delete e; 
} 
LogMessage("Done"); 

Diese DLL durch eine Drittanbieter-Anwendung geladen wird und der Code oben aufgerufen wird. Das Problem ist nur das erste LogMessage wird aufgerufen - obwohl es einen Ausnahme-Handler gibt, wird der Kontrollfluss zum Unbekannten übertragen.

Ich sehe das und kann mich nicht entscheiden, ob es sich um einen obskuren Bug handelt oder nur um die böse Kraft der Verbraucheranwendung.

Ist es wirklich möglich, dass eine Benutzeranwendung die C++ - Ausnahmebehandlung in einer DLL überschreibt?

EDIT: Das Problem gelöst nach dem Nachdenken über alle Dinge zu überprüfen in den Antworten skizziert. In echtem Code ist es nicht nur werfen, gibt es eine spezielle Funktion zum Auslösen von Ausnahmen, die einen Aufruf von MessageBoxW() Win32 Aufruf in der Debug-Version hat. Und die Verbraucheranwendung hatte Schwierigkeiten, die Nachrichtenbox zu zeigen (es ist ein NT-Dienst) und sie hat tatsächlich aufgelegt. Es ist also kein Problem der C++ - Ausnahmen in irgendeiner Weise.

Antwort

1

Der Code sieht OK für mich aus, aber ich wäre versucht, ein paar mehr Fangklauseln zu setzen, um zu sehen, ob es einen der anderen trifft. Das heißt, würde ich setzen in:

 
    catch (const std::exception &ex) { 
    ... log exception ... 
    } 
    catch (...) { 
    ... log exception .. 
    } 

Ich würde erwarten, dass es entweder den Zeiger Fang getroffen werden (auch wenn das ist wirklich keine gute Idee, finden Sie den Link, dass Igor Oks zur Verfügung gestellt) oder die std :: exception falls es den Speicher nicht zuordnen kann. Das heißt, es sollte eine der drei catch-Klauseln treffen, so dass die Ausnahme nicht aus der DLL entkommen kann.

Ich würde auch das Objekt in einen Werttyp ändern (auch wenn es int ist) und die catch -Klausel entsprechend aktualisieren, um zu sehen, ob Sie so ein verändertes Verhalten erhalten.

+0

Ich akzeptiere diese Antwort, weil sie die umfangreichste Liste von Dingen bietet, die man beim Debuggen solcher Probleme überprüfen kann. – sharptooth

1

Der Code ist OK. Ich ausgeführt es mit dieser Funktion:

void LogMessage(char* s) 
{ 
    cout << s << endl; 
} 

Und bekam die korrekte Ausgabe:

Hallo Welt

Gefangen Ausnahme

Geschehen

Ist es möglich, dass es ist ein Problem mit Ihrem Log Nachricht Funktion?

Ich würde vorschlagen zu untersuchen (durch Debugger oder Hinzufügen von Debug-Ausdrucken), ob Ihre Flüsse den try-Block erreicht, und ob es den catch-Block erreicht.

Kein Problem, es ist immer noch nicht klar, was erreichen Sie, indem Sie einen Zeiger und nicht einen Wert werfen. Ich würde empfehlen, nicht Catch-by-Pointer zu verwenden, siehe die Argumentation here, in der C++ - FAQ-Lite.

+0

Sehr unwahrscheinlich. Es funktioniert alles beim ersten Mal und es sieht so aus, als könnte nichts verhindern, dass es später richtig funktioniert. – sharptooth

1

Zuerst überprüfen Sie bitte, ob der LogMessage Aufruf den Ausgang löscht (verwenden Sie << endl).

Obwohl weit hergeholt, ist es möglich, dass der neue Aufruf eine Ausnahme (nicht genügend Speicher) wirft? Ich würde das als einen Grund betrachten, nicht zu neuen Ausnahmen (nur hinzuzufügen, was Igor sagte).

1

Der Code sieht gut aus. Aber können Sie überprüfen, ob es eine nicht behandelte Ausnahme gibt, bevor die strukturierte Ausnahme throw new int; ausgelöst wird.

LogMessage("Hello world"); 
try { 

    //some unhandled exception here 

    throw new int; 
} catch(int* e) { 
    LogMessage("Caught exception"); 
    delete e; 
} 
LogMessage("Done"); 

Wenn das der Fall ist, dann können Sie das gleiche mit SetUnhandledExceptionFilter Funktion überprüfen.

Wenn die DLL bereits einen unbehandelten Ausnahmefilter bereitstellt und wenn dieser EXCEPTION_EXECUTE_HANDLER zurückgibt, wird Ihr Ausnahmebehandler nicht aufgerufen.

Sie müssen _set_se_translator verwenden, um die Win32-Ausnahmen in C++ strukturierte Ausnahmen zu konvertieren.

0

Das Giveaway ist eigentlich in der EDIT. "MessageBoxW() ... NT-Dienst ... effektiv aufgelegt.". Das ist eine faire Beschreibung. Das Meldungsfeld befindet sich auf einem Desktop, der keinem angemeldeten Benutzer zugeordnet ist. Daher ist es immer noch da und wartet auf einen Mausklick, der niemals passieren wird.

Verwandte Themen