Frage

Ich arbeite an der Portierung einer Visual C++-Anwendung nach GCC (sollte auf MingW und Linux aufbauen).

Der vorhandene Code verwendet __try { ... } __except(1) { ... } blockiert an einigen Stellen, so dass fast nichts (außer möglicherweise nicht genügend Speichertypfehlern?) dazu führen würde, dass das Programm beendet wird, ohne eine minimale Protokollierung durchzuführen.

Welche Möglichkeiten gibt es, mit GCC etwas Ähnliches zu tun?

Bearbeiten:Vielen Dank für den Hinweis auf die /EH-Optionen in Visual Studio. Was ich jetzt brauche, sind einige Beispiele für den Umgang mit Signalen unter Linux.Ich habe gefunden diese Nachricht ab 2002.

Welche anderen Signale gibt es sonst noch? SIGFPE Und SIGSEVG sollte ich aufpassen?(Ich kümmere mich hauptsächlich um diejenigen, aus denen man erziehen könnte Mich etwas falsch machen)

Kopfgeldinformationen:Ich möchte, dass meine Anwendung so viele Fehlerbedingungen wie möglich selbst protokollieren kann, bevor sie beendet wird.

Welche Signale könnte ich erhalten und nach welchen würde es im Allgemeinen unmöglich sein, eine Fehlermeldung zu protokollieren?(Nicht mehr im Gedächtnis, was sonst?)

Wie kann ich Ausnahmen und (am wichtigsten) Signale portabel behandeln, damit der Code unter Linux und MingW zumindest gleich funktioniert?#ifdef ist in Ordnung.

Der Grund dafür, dass ich nicht nur einen Wrapper-Prozess habe, der den Fehler protokolliert, liegt darin, dass ich mir aus Leistungsgründen das Schreiben einiger Daten auf die Festplatte bis zur letzten Minute erspare. Wenn also etwas schief geht, möchte ich alle möglichen Versuche unternehmen, die Daten vorher zu schreiben verlassend.

War es hilfreich?

Lösung

try { xxx } Catch(...) { xxx } wäre portabler, fängt aber möglicherweise nicht so viel.Dies hängt von den Compilereinstellungen und Umgebungen ab.

Bei Verwendung der VC++-Standardeinstellungen werden asynchrone (SEH) Fehler nicht an die C++ EH-Infrastruktur übermittelt;Um sie abzufangen, müssen Sie stattdessen SEH-Handler (__try/__exclusiv) verwenden.Mit VC++ können Sie SEH-Fehler durch die C++-Fehlerbehandlung weiterleiten, wodurch ein Catch(...) SEH-Fehler abfangen kann.Dazu gehören Speicherfehler wie Nullzeiger-Dereferenzierungen. Einzelheiten.

Unter Linux werden jedoch viele der Fehler, für die Windows SEH verwendet, durch Signale angezeigt.Diese werden nie durch Try/Catch abgefangen;Um sie zu verarbeiten, benötigen Sie einen Signalhandler.

Andere Tipps

Warum nicht die C++-Standardausnahmen anstelle der proprietären Erweiterung von MSFT verwenden?C++ verfügt über ein Ausnahmebehandlungskonzept.

struct my_exception_type : public logic_error {
    my_exception_type(char const* msg) : logic_error(msg) { }
};

try {
    throw my_exception_type("An error occurred");
} catch (my_exception_type& ex) {
    cerr << ex.what << endl;
}

C++ verfügt außerdem über eine „catchall“-Klausel. Wenn Sie also Ausnahmen protokollieren möchten, können Sie den folgenden Wrapper verwenden:

try {
    // …
}
catch (...) {
}

Allerdings ist dies in C++ nicht sehr effizient, da die Erstellung eines solchen allgemeinen Wrappers bedeutet, dass Handling-Code eingefügt werden muss jeden Nachfolgender Stapelrahmen durch den Compiler (im Gegensatz zu verwalteten Systemen wie .NET, wo die Ausnahmebehandlung ohne zusätzliche Kosten erfolgt, solange keine Ausnahme tatsächlich ausgelöst wird).

Aus Gründen der Portabilität können Sie versuchen, für die meisten Vanilla-Ausnahmen Try-Catch-Blöcke zu verwenden und dann einen Terminate-Handler (set_terminate_handler) festzulegen, um einen minimalen Hook für katastrophale Exit-Bedingungen zur Verfügung zu haben.Sie können auch versuchen, so etwas wie einen atexit- oder on_exit-Handler hinzuzufügen.Natürlich kann Ihre Ausführungsumgebung bizarr oder beschädigt sein, wenn Sie diese Funktionen aufrufen. Seien Sie also vorsichtig, wie sehr Sie davon ausgehen, dass die Umgebung in Ordnung ist.

Schließlich können Sie bei der Verwendung regulärer Try-Catch-Paare die Verwendung von Funktions-Try-Blöcken in Betracht ziehen, anstatt einen Try-Block im Hauptteil einer Funktion zu öffnen:

int foo(int x) try {
  // body of foo
} catch (...) {
   // be careful what's done here!
}

Sie sind ein relativ unbekannter Teil von C++ und bieten in einigen Fällen möglicherweise eine Wiederherstellung selbst im Falle einer teilweisen (kleinen) Stapelbeschädigung.

Schließlich möchten Sie wahrscheinlich untersuchen, welche Signale Sie weiterhin alleine verarbeiten können oder bei welchen Sie abbrechen könnten. Wenn Sie weniger Verarbeitungsmechanismen wünschen, sollten Sie in Betracht ziehen, die nicht auslösende Version des neuen Operators aufzurufen und kompilieren, um bei Bedarf keine Gleitkomma-Ausnahmen zu generieren (Sie können jederzeit isnan(.), isfinite(.), auf FP-Ergebnissen überprüfen, um sich zu schützen).

Seien Sie in dieser letzten Anmerkung vorsichtig:Mir ist aufgefallen, dass sich die Gleitkomma-Ergebnisklassifizierungsfunktionen unter Linux und Windows in unterschiedlichen Headern befinden können ...Daher müssen Sie diese Includes möglicherweise konditionalisieren.

Wenn Sie sich zum Kobold fühlen, schreiben Sie alles mit setjmp und longjmp (das ist ein Witz ...).

C++-Ausnahmen abfangen mit catch(...) versetzt einen bereits in eine Zwielichtzone.

Es wird versucht, Fehler zu erkennen, die nicht erkannt wurden catch(...) versetzt Sie direkt in ein undefiniertes Verhalten.Es gibt keine Garantie dafür, dass C++-Code funktioniert.Ihr minimaler Protokollierungscode kann stattdessen dazu führen, dass die Rakete abgefeuert wird.

Meine Empfehlung ist, es gar nicht erst zu versuchen catch(...).Fangen Sie nur Ausnahmen ab, die Sie sinnvoll und sicher protokollieren können, und überlassen Sie den Rest, falls vorhanden, dem Betriebssystem.

Postmortem-Debugging wird hässlich, wenn neben der Grundursache auch Codefehler bei der Fehlerbehandlung auftreten.

Eine Möglichkeit, die einfach zu verwenden und portierbar ist und kaum Ressourcen verbraucht, wäre das Abfangen leerer Klassen.Ich weiß, das mag zunächst seltsam klingen, aber es kann sehr nützlich sein.

Hier ist ein Beispiel, das ich für eine andere Frage erstellt habe, das auch für Ihre Frage gilt: Verknüpfung

Sie können auch mehr als einen Fang haben:

try
{
   /* code that may throw exceptions */
}
catch (Error1 e1)
{
   /* code if Error1 is thrown */
}
catch (Error2 e2)
{
   /* code if Error2 is thrown */
}
catch (...)
{
   /* any exception that was not expected will be caught here */
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top