Ловить исключения нарушения прав доступа? - PullRequest
79 голосов
/ 19 января 2009

Пример

int *ptr;
*ptr = 1000;

могу ли я поймать исключение нарушения доступа к памяти, используя стандартный C ++, без использования каких-либо специфических для Microsoft.

Ответы [ 8 ]

102 голосов
/ 28 мая 2009

Прочтите и плачьте!

Я понял это. Если вы не выбросите обработчик, обработчик просто продолжит работу, как и исключение.

Магия случается, когда вы бросаете свое собственное исключение и обрабатываете его.

#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");

}
62 голосов
/ 23 ноября 2011

Существует очень простой способ отловить любое исключение (деление на ноль, нарушение доступа и т. Д.) В Visual Studio , используя блок try -> catch (...). Незначительные настройки проекта достаточно. Просто включите / EHa опцию в настройках проекта. См. Свойства проекта -> C / C ++ -> Генерация кода -> Установите для параметра Разрешить исключения C ++ значение «Да с исключениями SEH» . Вот и все!

Подробности здесь: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

36 голосов
/ 19 января 2009

Неа. C ++ не выдает исключение, когда вы делаете что-то плохое, что может привести к снижению производительности. Такие вещи, как нарушение доступа или деление на ноль ошибок, больше похожи на «машинные» исключения, а не на уровень языка, который вы можете поймать.

8 голосов
/ 19 января 2009

Этот тип ситуации зависит от реализации, и, следовательно, для перехвата потребуется специальный механизм поставщика. С Microsoft это будет связано с SEH, а * nix будет включать сигнал

В целом, хотя перехват исключения Access Violation является очень плохой идеей. Практически не существует способа восстановления после AV-исключения, и попытка сделать это просто приведет к тому, что будет сложнее найти ошибки в вашей программе.

7 голосов
/ 26 февраля 2017

По крайней мере для меня, подход signal(SIGSEGV ...), упомянутый в другом ответе , не работал на Win32 с Visual C ++ 2015 . Что сделало работа для меня, так это использование _set_se_translator(), найденное в eh.h. Это работает так:

Шаг 1 ) Убедитесь, что вы включили Да с исключениями SEH (/ EHa) в Свойства проекта / C ++ / Генерация кода / Включить исключения C ++ , как упомянутый в ответе Владимир Фрицкий .

Шаг 2 ) Вызовите _set_se_translator(), передав указатель функции (или лямбду) для нового исключения transator . Он называется переводчиком, потому что он в основном просто берет низкоуровневое исключение и перебрасывает его, как что-то более простое для перехвата, например 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();
};
7 голосов
/ 19 января 2009

Как уже говорилось, на платформе Windows не существует способов, не относящихся к Microsoft / поставщикам компиляторов. Однако, очевидно, полезно ловить эти типы исключений обычным способом try {} catch (exception ex) {} для сообщения об ошибках и более изящного выхода из вашего приложения (как говорит JaredPar, приложение теперь, вероятно, в беде) , Мы используем _se_translator_function в простой оболочке класса, которая позволяет нам перехватывать следующие исключения в обработчике try:

DECLARE_EXCEPTION_CLASS(datatype_misalignment)
DECLARE_EXCEPTION_CLASS(breakpoint)
DECLARE_EXCEPTION_CLASS(single_step)
DECLARE_EXCEPTION_CLASS(array_bounds_exceeded)
DECLARE_EXCEPTION_CLASS(flt_denormal_operand)
DECLARE_EXCEPTION_CLASS(flt_divide_by_zero)
DECLARE_EXCEPTION_CLASS(flt_inexact_result)
DECLARE_EXCEPTION_CLASS(flt_invalid_operation)
DECLARE_EXCEPTION_CLASS(flt_overflow)
DECLARE_EXCEPTION_CLASS(flt_stack_check)
DECLARE_EXCEPTION_CLASS(flt_underflow)
DECLARE_EXCEPTION_CLASS(int_divide_by_zero)
DECLARE_EXCEPTION_CLASS(int_overflow)
DECLARE_EXCEPTION_CLASS(priv_instruction)
DECLARE_EXCEPTION_CLASS(in_page_error)
DECLARE_EXCEPTION_CLASS(illegal_instruction)
DECLARE_EXCEPTION_CLASS(noncontinuable_exception)
DECLARE_EXCEPTION_CLASS(stack_overflow)
DECLARE_EXCEPTION_CLASS(invalid_disposition)
DECLARE_EXCEPTION_CLASS(guard_page)
DECLARE_EXCEPTION_CLASS(invalid_handle)
DECLARE_EXCEPTION_CLASS(microsoft_cpp)

Исходный класс взят из этой очень полезной статьи:

http://www.codeproject.com/KB/cpp/exception.aspx

3 голосов
/ 20 января 2009

Не механизм обработки исключений, Но вы можете использовать механизм signal (), предоставляемый C.

> man signal

     11    SIGSEGV      create core image    segmentation violation

Запись в нулевой указатель, вероятно, вызовет сигнал SIGSEGV

0 голосов
/ 19 января 2009

Подобное нарушение означает, что с кодом что-то серьезно не так, и оно ненадежно. Я вижу, что программа может попытаться сохранить данные пользователя таким образом, который, как можно надеяться, не будет записывать поверх предыдущих данных, в надежде, что данные пользователя еще не повреждены, но по определению не существует стандартного метода. иметь дело с неопределенным поведением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...