MS Visual Studio 2005 C ++ обработка исключений - PullRequest
1 голос
/ 21 октября 2011

У меня есть приложение C ++, встроенное в MS Visual Studio 2005, которое ссылается на стороннюю библиотеку. Для определенного ввода приложение вылетает в сторонней библиотеке (очевидно, где-то в realloc.c; поэтому должна быть проблема с памятью). Я побежал в выпуске, потому что вклад огромен. Таким образом, я бежал, пока он не падает, а затем решил отладить. В то время как я отдельно отлаживал виновную функцию, я надеялся использовать некоторую обработку исключений, чтобы предотвратить сбой приложения и вместо этого аккуратно завершить работу. Поэтому я использовал что-то вроде:

try {
   //- call 3rd party application function that fails
}
catch(...) {
   //- handle exception or whatever
   Logger::Fatal("Fatal error: Exiting...");
   return false;
}

Но, к моему удивлению, приложение все еще падает. Я ожидал, что он отобразит сообщение об ошибке, так как я предположительно перехватил все исключения с помощью многоточия (...); что мне здесь не хватает? Я даже пытался установить / EHca (был / EHsc) в Свойства проекта -> C / C ++ -> Конфигурация кода -> Включить обработку исключений. На соответствующей заметке о том, что может быть причиной проблемы, правильно ли следующее использование?

my_class* mc[] = {nil, nil, nil};
for (int i = 0; i < 3; ++i) {
    mc[i] = new my_class();
    //-Do stuff with mc[i]
    if (mc[i] != nil) {
       delete mc[i];
       mc[i] = nil;
    }
}

Неудача заставить работать обработку исключений довольно озадачивает. Я, безусловно, был бы признателен за идеи / идеи от гуру C ++ там. Кстати, та же проблема возникает и в Linux (RHEL5), но в настоящее время я пытаюсь заставить обработчик исключений работать в Windows.

ПРИМЕЧАНИЕ. Когда я разрешаю отладку после сбоя. Я получаю сообщение «Нарушение прав доступа ... невозможно прочитать местоположение». С этой обновленной информацией я надеялся, что что-то в C ++ все равно будет работать как на Windows, так и на Linux для таких сбоев.

Ответы [ 2 ]

1 голос
/ 21 октября 2011

Вы пытались поймать сбой, вызвав SetUnhandledExceptionFilter ?

0 голосов
/ 21 марта 2012

Как предположил Мигель, правильный способ решения вашей проблемы, вероятно, заключается в использовании SetUnhandledExceptionFilter.Но я все же хотел бы объяснить ваши феномены в деталях.

Прежде всего, не все сбои программы связаны с исключениями.Например, CRT может инициировать завершение программы при ошибках, таких как недопустимый доступ к элементу в vector или вызов чисто виртуального деструктора.Если вы хотите охватить и эти случаи - см. set_unexpected, set_terminate и т. Д.

Кроме того, блок catch может перехватывать только исключения, выданные из соответствующего блока кода.OTOH могут быть функции, которые вызываются в другом месте, такие как оконные процедуры (если применимо), другие потоки и т. Д.

Теперь относительно вашей проблемы.Давайте сначала поймем, почему такие вещи, как catch(...), могут отлавливать такие вещи, как нарушение доступа и т. Д., И почему это не всегда происходит (как в вашем случае).

В Windows предусмотрен собственный механизм обработки исключений - SEH, структурированныйОбработка исключений.Это намного превосходит обработку исключений в C ++.Кроме того, аппаратные прерывания (вызванные ЦП) автоматически «преобразуются» в исключения SEH, поэтому код, использующий SEH, обрабатывает как программные исключения, так и аппаратные сбои.

Компиляторы Microsoft C ++ фактически реализуют исключения C ++ черезSEH .То есть throw реализуется через RaiseException с указанием C ++-специфичного кода и параметров исключений, catch является C ++ -специфичной оболочкой для __except, и для каждого объекта с деструктором компилятор генерирует что-то похожее на __finallyблок.И это также работает наоборот.Когда возникает исключение не-C ++ - выполняется тот же код, сгенерированный для исключений C ++.

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

  • синхронный .Компилятор генерирует код, который гарантированно будет работать правильно, только если исключения вызываются явно.Это включает throw статистики и все «чужие» функции, чей код не виден компилятору (в некоторых вариантах - только внешние функции C ++).В частности, чтение из памяти считается «безопасным».
  • асинхронный .Компилятору не разрешается предполагать, что могут возникнуть исключения.Следовательно, он генерирует код, который должен работать правильно, даже если исключение возникает из-за доступа к адресу памяти.

Кроме того, код CRT, который вызывается в catch (...) , намеренно игнорирует исключения не-C ++,если не выбрана асинхронная модель EH .

Так что, если вы хотите, чтобы catch (...) перехватывал исключения не-C ++ - вы должны выбрать асинхронную модель EH.

Как только я написал статью по проекту кода , после того, как у меня возникла проблема в разработке драйверов.Это объясняет все это в деталях.

...