Поймать исключение во время выполнения - PullRequest
1 голос
/ 23 августа 2010

После не удается поймать исключение

int *i;  //intentionally uninitialized

try {
      *i = 6;
    }
catch (const runtime_error e) {
      cout << "caught!" << endl;
    }

это действительно перехват ошибки во время выполнения или исключение?

Ответы [ 6 ]

4 голосов
/ 23 августа 2010

Строка *i = 6; не выбрасывает runtime_error; это приводит к неопределенному поведению.

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

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

3 голосов
/ 23 августа 2010

Отказ от ответственности

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

При этом я думаю, что лучше ответить на вопрос, чем выносить суждение, осуждать или подвергать цензуреit.


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

Хуже того, исключения C ++ не могут проходить вне обработчика сигнала (то, что в других языках будет называться «обработчиком исключения»), функция, котораяпризвал к незаконному доступу).Стандарт имеет специальное предупреждение об этом:

[простая старая функция], которая может использоваться в качестве обработчика сигнала в соответствующей программе на C, не дает неопределенного поведения при использовании в качестве обработчика сигнала вC ++ программа.Поведение любой другой функции, используемой в качестве обработчика сигнала в программе на C ++, определяется реализацией.213)

213) В частности, обработчик сигнала, использующий обработку исключений, с большой вероятностью может иметь проблемы

Тем не менее, если вы хотите поймать это, используйте средство UNIX signal для установки функции, которая не использует функции C ++.

#include <csignal>
#include <cstdlib>
#include <cstdio>

void catch_memory( int ) {
    std::printf( "caught!\n" );
    std::abort();
}

int main() {
    std::signal( SIGSEGV, catch_memory );

    int *i = 0;
    *i = 6;
}
1 голос
/ 23 августа 2010

Соответствующее предложение catch выполняется, когда выбрасывается соответствующее исключение с использованием ключевого слова throw C ++. Это исключения C ++.

То, что вы получаете с кодом OP, вероятно, является сгенерированным системой исключением (не исключением C ++), и, строго говоря, это неопределенное поведение.

1 голос
/ 23 августа 2010

Это не ошибка времени выполнения, это неопределенное поведение времени выполнения из-за ошибки времени компиляции .

Чтобы поймать это (и многие другие, как это), установите свой компилятор на максимально возможный уровень предупреждения. (Как компиляторы, вопреки комментарию Мартина, do проверяет, не глупы ли вы, если позволите.) gcc -Wall сделал бы это в этом случае:

$ g++ -Wall test.cpp 
test.cpp: In function ‘int main()’:
test.cpp:<line>: warning: ‘i’ is used uninitialized in this function

Лично я предпочитаю что-то вроде этого:

$ CXXWARN="-Wall -Wextra -Werror -pedantic -Wno-unused-parameter \
         -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \
         -Wmissing-declarations -Wredundant-decls -Winline"
$ g++ $CXXWARN test.cpp

Ваш пробег может отличаться.

0 голосов
/ 23 августа 2010

Microsoft создала нечто, называемое структурированные исключения несколько лет назад (иначе, SEH для "обработки структурированных исключений").Хотя между исключениями C ++ и структурированными исключениями есть некоторое сходство, это принципиально разные вещи.Лично я держался подальше от SEH.

SEH позволяет, помимо прочего, распознавать, когда стек переполнен или имеет место нарушение доступа к памяти.Дело в том, что вы ничего не можете сделать в этих случаях: состояние вашей программы было безвозвратно нарушено до того, как ваш обработчик получил шанс на запуск.И хотя вы не можете исправить «безвозвратно поврежденный», ваш обработчик может утверждать, что он это сделал (то есть вы можете продолжить выполнение, даже если ваш стек был разбит).

Таким образом, ваш блок catch не выполняетсяпотому что исключение, которое вы пытаетесь поймать, является специфичным для Windows расширением, использующим совершенно другую систему.

0 голосов
/ 23 августа 2010

Это не исключение. Это может привести к аварии. Если вы работаете в проекте, во-первых, проверьте его у коллег. Обзоры кода очень полезны большую часть времени. Если нет, вы можете обнаружить такие ошибки в начале цикла разработки, используя инструменты статического анализа кода, такие как Klocwork, и инструменты динамического анализа кода, такие как Purify, Bounds Checker и т. Д.

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