100 Stimmen

Abfangen von Ausnahmen bei Zugriffsverletzungen?

Ejemplo

int *ptr;
*ptr = 1000;

kann ich mit Standard-C++ eine Ausnahme von der Speicherzugriffsverletzung abfangen, ohne dass ich eine microsoft-spezifische.

118voto

Lesen Sie es und weinen Sie!

Ich habe es herausgefunden. Wenn Sie nicht aus dem Handler werfen, wird der Handler einfach weiter und so wird die Ausnahme.

Die Magie geschieht, wenn Sie Ihre eigene Ausnahme auslösen und diese behandeln.

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <tchar.h>

void SignalHandler(int signal)
{
    printf("Signal %d",signal);
    throw "!Access Violation!";
}

int main()
{
    typedef void (*SignalHandlerPointer)(int);

    SignalHandlerPointer previousHandler;
    previousHandler = signal(SIGSEGV , SignalHandler);
    try{
        *(int *) 0 = 0;// Baaaaaaad thing that should never be caught. You should write good code in the first place.
    }
    catch(char *e)
    {
        printf("Exception Caught: %s\n",e);
    }
    printf("Now we continue, unhindered, like the abomination never happened. (I am an EVIL genius)\n");
    printf("But please kids, DONT TRY THIS AT HOME ;)\n");

}

74voto

Volodymyr Frytskyy Punkte 1193

Es gibt eine sehr einfache Möglichkeit, jede Art von Ausnahme (Division durch Null, Zugriffsverletzung usw.) in Visual Studio mit try -> catch (...) Block. Eine kleine Änderung der Projekteinstellungen ist ausreichend. Aktivieren Sie einfach die Option /EHa in den Projekteinstellungen. Siehe Projekteigenschaften -> C/C++ -> Codegenerierung -> Ändern Sie die Option C++-Ausnahmen aktivieren auf "Ja mit SEH-Ausnahmen". . Das war's!

Einzelheiten finden Sie hier: https://docs.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-160

48voto

unwind Punkte 377331

Nö. C++ löst keine Ausnahme aus, wenn Sie etwas Schlechtes tun, was einen Leistungseinbruch zur Folge hätte. Dinge wie Zugriffsverletzungen oder Fehler bei der Division durch Null sind eher "Maschinen"-Ausnahmen als Dinge auf Sprachebene, die man abfangen kann.

14voto

Michael Punkte 2100

Zumindest für mich ist die signal(SIGSEGV ...) in einer anderen Antwort erwähnter Ansatz funktionierte nicht auf Win32 mit Visual C++ 2015 . Was hat Arbeit für mich war die Verwendung von _set_se_translator() gefunden in eh.h . Das funktioniert folgendermaßen:

Schritt 1 ) Stellen Sie sicher, dass Sie die Ja mit SEH-Ausnahmen (/EHa) en Projekteigenschaften / C++ / Codegenerierung / C++-Ausnahmen aktivieren wie in der Antwort von Wolodymyr Frytskyy .

Schritt 2 ) Aufruf _set_se_translator() mit der Übergabe eines Funktionszeigers (oder Lambdas) für die neue Ausnahme Übersetzer . Es wird als Übersetzer bezeichnet, weil es im Grunde nur die Low-Level-Ausnahme nimmt und sie in etwas leichter Abfangbares umwandelt, z. B. in std::exception :

#include <string>
#include <eh.h>

// Be sure to enable "Yes with SEH Exceptions (/EHa)" in C++ / Code Generation;
_set_se_translator([](unsigned int u, EXCEPTION_POINTERS *pExp) {
    std::string error = "SE Exception: ";
    switch (u) {
    case 0xC0000005:
        error += "Access Violation";
        break;
    default:
        char result[11];
        sprintf_s(result, 11, "0x%08X", u);
        error += result;
    };
    throw std::exception(error.c_str());
});

Schritt 3 ) Fangen Sie die Ausnahme wie gewohnt ab:

try{
    MakeAnException();
}
catch(std::exception ex){
    HandleIt();
};

10voto

JaredPar Punkte 699699

Diese Art von Situation hängt von der Implementierung ab und erfordert daher einen herstellerspezifischen Mechanismus, um eine Falle zu stellen. Bei Microsoft ist dies SEH, bei *nix ist es ein Signal

Im Allgemeinen ist das Abfangen einer Access Violation Exception jedoch eine sehr schlechte Idee. Es gibt fast keine Möglichkeit, sich von einer AV-Ausnahme zu erholen, und der Versuch, dies zu tun, führt nur zu schwer zu findenden Fehlern in Ihrem Programm.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X