Почему моя программа не ловит исключение из разыменования нулевого указателя? - PullRequest
4 голосов
/ 01 сентября 2011

Может кто-нибудь объяснить, почему это исключение не поймано.

try {
    // This will cause an exception
    char *p = 0;
    char x = 0;
    *p = x;
}
catch (...) {
    int a = 0;
}

Когда я запускаю программу, она умирает на линии * p = x. Я ожидаю, что блок catch вызовет игнорирование этого исключения.

Я использую Qt Creator (2.2) с Qt 4.7.2, компилируемую с Visual Studios 2008 на 32-битной Windows 7.

Ответы [ 7 ]

10 голосов
/ 01 сентября 2011

Здесь не выдается исключение C ++. Вы вызываете неопределенное поведение , потому что *p = x разыменовывает указатель с нулевым значением указателя.

Исключение распространяется только тогда, когда вы или вызываемый вами код выполняете выражение throw. Неопределенное поведение обычно не catch способен.

3 голосов
/ 01 сентября 2011

Если вы хотите, чтобы вы написали тест указателя:

template<typename T>
inline T* ptr_test(T* test)
{
    if (test == NULL)
    {    throw std::runtime_error("Null Exceception");
    }
    return test;
}

Тогда ваш код выглядит так:

try
{
    // This will cause an exception
    char* p = 0;
    char  x = 0;
    *ptr_test(p) = x;  // This is what java does.
                       // Fortunately C++ assumes you are smart enough to use pointers correctly.
                       // Thus I do not need to pay for this test.
                       //
                       // But if you want to pay for the test please feel free.
}
catch (...) 
{
    int a = 0;
}
3 голосов
/ 01 сентября 2011

Разыменование нулевого указателя - неопределенное поведение.Как правило, это вызывает прерывание процессора и ошибку уровня ОС.Затем это может быть сопоставлено с сигналом, таким как SIGSEGV, или с ошибкой нарушения прав доступа, или оно может прервать вашу программу или сделать что-либо еще.

В Windows оно сопоставлено со "структурированнымисключение ", которое отличается от исключения C ++.В зависимости от того, как вы настроили MSVC, вы можете поймать это с помощью catch(...), но не всегда.

2 голосов
/ 01 сентября 2011

Структурированная обработка исключений __try и __catch обнаружат системные ошибки, см .:

http://msdn.microsoft.com/en-us/library/swezty51(v=vs.80).aspx

1 голос
/ 01 сентября 2011

Вам необходимо использовать опцию компилятора /EHa, чтобы включить функцию (компилятор Microsoft специфичный ), которая включит SEH ( Структурная обработка исключений ) исключения (то, что вызывает ваш нулевой доступ), которые можно перехватить catch(...).

Сказав это, я бы не рекомендовал использовать /EHa. Лучше использовать расширение __try/__except или SEH API напрямую и держать обработку «структурированных» исключений отдельно от обработки исключений C ++. Зачем ? Поскольку исключения C ++ - это просто еще один вполне законный четко определенный механизм потока управления, но большинство вещей, которые вызывают исключения SEH, могут указывать на то, что ваше программное обеспечение вошло в область неопределенного поведения, и на самом деле единственная разумная вещь, которую нужно сделать, это выйти изящно. Использование / EHa приводит к тому, что это существенное различие становится излишне размытым.

1 голос
/ 01 сентября 2011

Все, что вы сейчас делаете, это разыменовываете нулевой указатель, это не исключение.

Если вы хотите, чтобы этот код что-то перехватывал, вы должны сначала что-то бросить.Скажем, что-то вроде:

try {
    // This will cause an exception
    char *p = 0;
    char x = 0;
    if (p == 0) throw 1;
    *p = x;
}
catch (...) {
    int a = 0;
}

Очевидно, что блок catch в приведенном выше примере всегда будет выполняться.

1 голос
/ 01 сентября 2011

Это не пойман, потому что это не исключение - ничего не выбрасывает.Вы обращаетесь к нулевой / нераспределенной памяти, которая вызывает ошибку сегментации, которая является сигналом самой операционной системы.

Сигналы могут быть перехвачены только обработчиками сигналов, исключения не помогут вам в этом.

Исключения действительно помогают только в тех областях, где что-то может вызывать throw (), например, библиотека выдает исключение, когда вы делите на ноль с параметрами, которые вы указали.

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