Przykład
int *ptr;
*ptr = 1000;
czy mogę przechwycić wyjątek naruszenia dostępu do pamięci przy użyciu standardowego C ++ bez użycia jakichkolwiek specyficznych dla firmy Microsoft.
c++
exception-handling
Ahmed Said
źródło
źródło
Przeczytaj i płacz!
Rozgryzłem to. Jeśli nie wyrzucisz z handlera, handler będzie kontynuował, podobnie jak wyjątek.
Magia dzieje się, gdy rzucasz własny wyjątek i radzisz sobie z tym.
#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"); }
źródło
sigaltstack
zainstalowane żadne alternatywne stosy sygnałów ( ) (chyba, że implementacja cofania wyjątku C ++ na to pozwala), a każda funkcja środowiska uruchomieniowego obsługująca sam mechanizm rozwijania powinna być bezpieczna dla sygnałów.signal(SIGSEGV, SIG_DFL);
Istnieje bardzo łatwy sposób na wychwycenie dowolnego rodzaju wyjątku (dzielenie przez zero, naruszenie zasad dostępu itp.) W programie Visual Studio przy użyciu bloku try -> catch (...). Wystarczy drobna zmiana ustawień projektu. Po prostu włącz opcję / EHa w ustawieniach projektu. Zobacz Właściwości projektu -> C / C ++ -> Generowanie kodu -> Zmodyfikuj opcję Włącz wyjątki C ++ na „Tak z wyjątkami SEH” . Otóż to!
Zobacz szczegóły tutaj: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
źródło
Przynajmniej dla mnie
signal(SIGSEGV ...)
podejście wymienione w innej odpowiedzi nie działało na Win32 z Visual C ++ 2015 . Co zrobiłem pracę dla mnie było wykorzystanie_set_se_translator()
znaleźć weh.h
. Działa to tak:Krok 1 ) Upewnij się, że włączyłeś Tak z SEH Exceptions (/ EHa) we właściwościach projektu / C ++ / Code Generation / Enable C ++ Exceptions , jak wspomniano w odpowiedzi Volodymyr Frytskyy .
Krok 2 ) Wywołaj
_set_se_translator()
, przekazując wskaźnik funkcji (lub lambda) dla nowego translatora wyjątków . Nazywa się to tłumaczem, ponieważ po prostu bierze wyjątek niskiego poziomu i ponownie rzuca go jako coś łatwiejszego do złapania, na przykładstd::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()); });
Krok 3 ) Złap wyjątek tak, jak zwykle:
try{ MakeAnException(); } catch(std::exception ex){ HandleIt(); };
źródło
Tego typu sytuacja jest zależna od implementacji, w związku z czym pułapka będzie wymagała specjalnego mechanizmu dostawcy. W przypadku Microsoftu będzie to wiązało się z SEH, a * nix będzie wiązało się z sygnałem
Ogólnie jednak wyłapywanie wyjątku naruszenia zasad dostępu jest bardzo złym pomysłem. Nie ma prawie żadnego sposobu na odzyskanie po wyjątku AV, a próba wykonania tego spowoduje trudniejsze znalezienie błędów w programie.
źródło
Jak wspomniano, nie ma sposobu, w jaki producent inny niż Microsoft / kompilator może to zrobić na platformie Windows. Jednak ewidentnie przydatne jest wychwycenie tego typu wyjątków w normalny sposób try {} catch (wyjątek ex) {} do raportowania błędów i bardziej wdzięcznego wyjścia z aplikacji (jak mówi JaredPar, aplikacja prawdopodobnie ma teraz kłopoty) . Używamy _se_translator_function w prostym opakowaniu klasy, które pozwala nam wychwycić następujące wyjątki w obsłudze aa try:
Oryginalna klasa pochodzi z tego bardzo przydatnego artykułu:
http://www.codeproject.com/KB/cpp/exception.aspx
źródło
Nie mechanizm obsługi wyjątków, ale możesz użyć mechanizmu signal (), który jest udostępniany przez C.
> man signal 11 SIGSEGV create core image segmentation violation
Zapis do wskaźnika NULL prawdopodobnie spowoduje sygnał SIGSEGV
źródło
signal()
jest częścią standardu POSIX . Windows implementuje standard POSIX (podobnie jak Linux i unix)Takie naruszenie oznacza, że z kodem jest coś poważnego i jest on zawodny. Widzę, że program może chcieć spróbować zapisać dane użytkownika w sposób, który ma nadzieję, że nie zostanie zapisany na poprzednich danych, w nadziei, że dane użytkownika nie są już uszkodzone, ale z definicji nie ma standardowej metody radzenia sobie z niezdefiniowanym zachowaniem.
źródło