2013-02-06 5 views
10

Ich arbeite an einer performance-kritischen dynamisch verbundenen Bibliothek (DLL), die auch eine relativ kleine binäre Größe haben sollte. Da Ausnahmen nicht explizit ausgelöst werden, möchte ich die Ausnahmeunterstützung ganz deaktivieren. Es gibt jedoch eine Ausnahme (unbeabsichtigtes Wortspiel): Wenn ich nicht genügend Arbeitsspeicher (OOM) habe, muss ich der Anwendung einen Fehlercode melden, damit sie die Möglichkeit hat, die Dinge elegant zu behandeln. Die Codebasis ist zu groß, um jede Zuordnung einzeln zu überprüfen und den Fehler zu propagieren, und enthält externen Code, den ich nicht berühren sollte. Daher möchte ich OOM-Ausnahmen in den exportierten Funktionen meiner DLL abfangen.Wie kann die Out-of-Memory-Robustheit bei deaktivierten C++ - Ausnahmen (VS2010) sichergestellt werden?

Ein schneller Test zeigt, dass beim Deaktivieren von C++ - Ausnahmen in Visual C++ 2010 (dh keine/EHa,/EHsc oder/EHs Flags) immer noch zu einem Catch (Std :: bad_alloc &) Block bei der Zuordnung zu viel Speicher springt .

So scheint es wie gewünscht zu arbeiten. Ich erhalte jedoch die folgende Warnung der Stufe 1: "C4530: C++ - Ausnahmebehandler verwendet, aber Abwicklungssemantik ist nicht aktiviert. Geben Sie/EHsc" an. MSDN sagt, dass "ein Objekt mit automatischer Speicherung im Rahmen zwischen der Funktion, die den Wurf ausführt, und der Funktion, die den Wurf fängt, nicht zerstört wird".

Genau was würde ich hier verlieren? Es ist in Ordnung, Dinge in einem undefinierten Zustand zu belassen, solange alles, was über die Bibliothek erstellt wurde, gelöscht werden kann und die Anwendung von Neuem beginnen kann (falls sie dies wünscht). Besteht ein großes Risiko, Speicher zu verlieren, die nicht wiederhergestellt werden können?

Verwenden DLLs einen separaten Speicherpool? Und wenn ja, kann ich es löschen, ohne dass die Anwendung die DLL entladen muss? Ich kann meine Bibliothek leicht dazu bringen, weitere (exportierte) Funktionsaufrufe zu ignorieren, bis die Anwendung eine Neuinitialisierung durchführt.

Vielen Dank für Ihren Rat.

+0

* Verwenden DLLs einen separaten Speicherpool? * Http://stackoverflow.com/questions/10820114/do-statisch-verknüpfte-dlls-use-a-different-hea-the-main-program – thang

+0

* Und wenn ja, kann ich es löschen, ohne dass die Anwendung die DLL entladen muss? * Yeah, löschen Sie einfach das Zeug von neu und befreien Sie das Zeug von malloc. – thang

+1

Keine Ausnahmebehandlung bedeutet, dass Objekte, die auf dem Stapel (und in einem Konstruktor, der fehlschlägt) erstellt werden, nicht zerstört werden. Wenn Sie nur gehen, wenn der 'bad_alloc' passiert, dann geht es Ihnen gut, ich nehme an (solange Sie keine merkwürdigen Ressourcen haben, die nicht mit Programm-Exit aufgeräumt werden - aber die meisten sollten]. Wenn Sie nach "bad_alloc" fortfahren möchten, muss der Code Objekte verfolgen und alle Objekte zerstören, die in Stapelrahmen zwischen "throw" und "catch" erstellt wurden. Sie können experimentieren, indem Sie einen kleinen Code schreiben, der Ausdrucke in Destruktoren enthält. –

Antwort

1

Einige Präliminarien:

Ich weiß nicht, ob eine Ausnahme ohne Ausnahmebehandlung wirft durch den Standard aktiviert ist nicht definiertes Verhalten oder nicht, aber Sie werden sicherlich nicht Abwickeln/destructor Anrufe von Ihrem Objekte stapeln erhalten auf dem Stapel.

Wenn Sie C++ - Code mit RAII für Mutexe, Dateien, Speicher usw. schreiben, ist dies eine sehr schlechte Sache.

Umzug auf dann, und Ihren Code unter der Annahme, im Wesentlichen C-Stil-Code:

1) Wenn Sie statisch auf die C-Laufzeitbibliothek verknüpfen, Ihre DLL nicht einen Haufen mit Hauptanwendung teilen. Das Entladen der DLL sollte den ausgelaufenen Speicher freigeben - aber auch andere Ressourcen sollten berücksichtigt werden.

2) Wenn Sie dynamisch mit der C-Laufzeit verknüpfen (ziemlich häufig), dann teilen Sie einen Heap. Sie müssen einen Weg haben, um den von der DLL zugewiesenen Speicher manuell freizugeben.

Da ich selbst viel zu viel mit DLL-Grenzproblemen herumgespielt habe, würde ich ein kurzes Benchmarking empfehlen, um zu sehen, wofür Sie bezahlen, wenn Ausnahmen aktiviert bleiben. Abhängig von Ihrer Plattform und Ihrem Compiler können untrügliche Ausnahmen eine vernachlässigbare Auswirkung auf die Leistung haben.

+0

Es ist kein Code im C-Stil, und ein bedeutender Teil davon steht nicht unter meiner Kontrolle. Zwar vertraue ich diesem Code von Drittanbietern im Normalbetrieb, aber wenn eine OOM-Ausnahme ausgelöst wird, kann ich keine Annahmen treffen, unabhängig davon, ob die Ausnahmebehandlung aktiviert ist. "_Sie müssen eine Möglichkeit haben, manuell zugewiesenen Speicher aus der DLL freizugeben. _" Genau darum geht es in meiner Frage. :-) –

+0

Sorry, aber ich denke dann, dass es wirklich keine Möglichkeit gibt, das zu tun, was du willst. Um die "manuelle Freigabe von der DLL" in meinen eigenen Plug-in-Systemen zu erreichen, muss der gesamte Client-Code mithilfe einer benutzerdefinierten Zuweisungsroutine zugewiesen werden, die mein Kern an die DLL liefert. Diese Zuordnung ermöglicht es dem Kern, eine DLL so zu löschen, wie Sie möchten. Aber wenn Sie das nicht selbst durchsetzen können, dann glaube ich nicht, dass es getan werden kann. – Stephen