пример
int *ptr;
*ptr = 1000;
Могу ли я поймать исключение нарушения доступа к памяти с помощью стандартного C ++ без использования каких-либо конкретных Microsoft.
c++
exception-handling
Ахмед Саид
источник
источник
Прочтите и плачьте!
Я понял. Если вы не выбрасываете из обработчика, обработчик просто продолжит работу, как и исключение.
Магия происходит, когда вы генерируете собственное исключение и обрабатываете его.
#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"); }
источник
sigaltstack
) (если это не разрешено реализацией разматывания исключений C ++), и каждая функция времени выполнения, обрабатывающая сам механизм разматывания, должна быть безопасной для сигналов.signal(SIGSEGV, SIG_DFL);
Существует очень простой способ перехвата любого типа исключения (деление на ноль, нарушение прав доступа и т. Д.) В Visual Studio с помощью блока try -> catch (...). Достаточно незначительной настройки параметров проекта. Просто включите опцию / EHa в настройках проекта. См. Свойства проекта -> C / C ++ -> Генерация кода -> Измените параметр Включить исключения C ++ на «Да с исключениями SEH» . Это оно!
Подробности см. Здесь: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
источник
По крайней мере, для меня
signal(SIGSEGV ...)
подход, упомянутый в другом ответе , не работал на Win32 с Visual C ++ 2015 . Что действительно работало для меня, так это использовать_set_se_translator()
найденное вeh.h
. Это работает так:Шаг 1 ) Убедитесь, что вы включили Да с исключениями SEH (/ EHa) в свойствах проекта / C ++ / Генерация кода / Включить исключения C ++ , как указано в ответе Владимира Фрицкого .
Шаг 2 ) Вызов
_set_se_translator()
, передав указатель функции (или лямбда) для нового транслятора исключений . Он называется переводчиком, потому что он просто принимает низкоуровневое исключение и повторно генерирует его, как что-то более легкое для улова, например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()); });
Шаг 3 ) Перехватите исключение, как обычно:
try{ MakeAnException(); } catch(std::exception ex){ HandleIt(); };
источник
Этот тип ситуации зависит от реализации и, следовательно, для перехвата требуется специальный механизм поставщика. В Microsoft это будет включать SEH, а * nix будет включать сигнал
В общем, хотя перехват исключения нарушения прав доступа - очень плохая идея. Восстановиться после исключения AV практически невозможно, и попытка сделать это только усложнит поиск ошибок в вашей программе.
источник
Как уже говорилось, на платформе Windows нет способа сделать это сторонним поставщиком / поставщиком компилятора. Однако, очевидно, полезно перехватывать эти типы исключений обычным способом try {} catch (exception ex) {} для сообщения об ошибках и, более того, для плавного выхода из вашего приложения (как говорит JaredPar, приложение, вероятно, сейчас в беде) . Мы используем _se_translator_function в простой оболочке класса, которая позволяет нам перехватывать следующие исключения в обработчике попытки:
Исходный класс взят из этой очень полезной статьи:
http://www.codeproject.com/KB/cpp/exception.aspx
источник
Не механизм обработки исключений, но вы можете использовать механизм signal (), который предоставляется C.
> man signal 11 SIGSEGV create core image segmentation violation
Запись в указатель NULL, вероятно, вызовет сигнал SIGSEGV
источник
signal()
является частью стандарта posix. Windows реализует стандарт posix (как и Linux и unix)Такое нарушение означает, что с кодом что-то серьезно не так, и это ненадежно. Я вижу, что программа может захотеть попытаться сохранить данные пользователя таким образом, чтобы можно было надеяться, что они не будут записывать поверх предыдущих данных, в надежде, что данные пользователя еще не повреждены, но стандартного метода по определению не существует. работы с неопределенным поведением.
источник