Может ли неуправляемое исключение первого шанса вызвать сбой / перезапуск?

Последующие вопросы: "При расследовании аварии я должен исследовать только исключения второго шанса? В каких случаях мне также нужно исследовать дамп исключения первого шанса?"

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

РЕДАКТИРОВАТЬ: Вот примеры статей, но есть еще много других:

Что такое исключение для первого шанса?:

"Для кода без обработки исключений отладчик получит уведомление об исключении второго шанса и остановится с необработанным исключением".

Программа вылетает, но Debug Diag говорит, что это исключение из первого шанса, это правильно?

Конечно, по определению, только второе случайное исключение может привести к сбою кода, то есть то, которое НЕ было обработано кодом?

У меня периодически возникает проблема, когда мое приложение перезагружается или происходит сбой (нет ошибки в средстве просмотра событий), но перед перезапуском Adplus генерирует некоторые первые исключения AccessViolation. Никаких исключений второго шанса.

Ниже приведен фрагмент FULLDUMP_FirstChance_av_AccessViolation для WinDbg.exe:

PROBLEM_CLASSES: 
HEAP_CORRUPTION
    Tid    [0x16e8]
    Frame  [0x02]: ntdll!RtlAllocateHeap
HEAP_CORRUPTION
    Tid    [0x16e8]
    Frame  [0x02]: ntdll!RtlAllocateHeap
INVALID_POINTER_READ
    Tid    [0x16e8]
    Frame  [0x00]: ntdll!ExpInterlockedPopEntrySListFault
NOSOS
    Tid    [0x16e8]
BUGCHECK_STR:  HEAP_CORRUPTION_HEAP_CORRUPTION_INVALID_POINTER_READ_NOSOS

Образцы стеков вызовов ниже:

# ChildEBP RetAddr  Args to Child              
00 085aec28 7c91020e 00000007 00c407d8 00c40000 ntdll!ExpInterlockedPopEntrySListFault (FPO: [0,2,0])
01 085aec58 7c91019b 00c407d8 00000030 00000000 ntdll!RtlpAllocateFromHeapLookaside+0x1d (FPO: [Non-Fpo])
02 085aee84 78134d83 00c40000 00000000 00000030 ntdll!RtlAllocateHeap+0x1c2 (FPO: [Non-Fpo])
03 085aeea4 78160e30 00000030 0000002f 085aeecc msvcr80!malloc(unsigned int size = 0x30)+0x7a (FPO: [1,0,0]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163]
04 085aeebc 7c4221b3 00000030 00000003 7c422f20 msvcr80!operator new(unsigned int size = 0x30)+0x1d (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\new.cpp @ 59]
05 085aeed4 7c423315 00000030 00000000 ae218f51 msvcp80!std::_Allocate<char>(unsigned int _Count = 0x30, char * __formal = 0x00000000 "")+0x15 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\xmemory @ 44]
06 085aef0c 7c4233c4 0000002a 00000000 085af028 msvcp80!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Copy(unsigned int _Newsize = 0x2a, unsigned int _Oldlen = 0)+0x55 (FPO: [Non-Fpo]) (CONV: thiscall) [f:\dd\vctools\crt_bld\self_x86\crt\src\xstring @ 2020]
07 085aef20 7c423779 0000002a 00000000 085af200 msvcp80!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Grow(unsigned int _Newsize = 0x2a, bool _Trim = false)+0x22 (FPO: [2,0,0]) (CONV: thiscall) [f:\dd\vctools\crt_bld\self_x86\crt\src\xstring @ 2050]
08 085aef3c 7c425e55 0000002a 00000000 0000002a msvcp80!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::append(class std::basic_string<char,std::char_traits<char>,std::allocator<char> > * _Right = 0x0000002a, unsigned int _Roff = 0, unsigned int _Count = 0x2a)+0x58 (FPO: [Non-Fpo]) (CONV: thiscall) [f:\dd\vctools\crt_bld\self_x86\crt\src\xstring @ 969]
09 085aef4c 60baed1e 085af028 ae262fd2 085af1a4 msvcp80!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::append(class std::basic_string<char,std::char_traits<char>,std::allocator<char> > * _Right = 0x085af028 " S1 S1 Card number:    ************8706  
")+0xd (FPO: [1,0,0]) (CONV: thiscall) [f:\dd\vctools\crt_bld\self_x86\crt\src\xstring @ 956]
0a 085af1a4 7c802662 00000100 00000000 00000000 aipoptrv19!DllUnregisterServer+0x1f15e
0b 085af234 7c42317a 00000000 00000000 0000000f kernel32!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
0c 085af274 60bc1fd8 60baa1cb 0865d680 0000001c msvcp80!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> >(void)+0x11 (FPO: [0,0,4]) (CONV: thiscall) [f:\dd\vctools\crt_bld\self_x86\crt\src\xstring @ 576]
0d 085af278 60baa1cb 0865d680 0000001c 00000002 aipoptrv19!DllUnregisterServer+0x32418
0e 085af2e4 60bb227c 00000001 085af420 0865d648 aipoptrv19!DllUnregisterServer+0x1a60b
0f 085af34c 7c425e45 085af404 00000000 ffffffff aipoptrv19!DllUnregisterServer+0x226bc
10 085af35c 60b97724 72506f44 69746e69 0000676e msvcp80!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::assign(class std::basic_string<char,std::char_traits<char>,std::allocator<char> > * _Right = 0x72506f44)+0xd (FPO: [1,0,0]) (CONV: thiscall) [f:\dd\vctools\crt_bld\self_x86\crt\src\xstring @ 1044]
11 085af45c 78261414 00000002 403110f4 7824f516 aipoptrv19!DllUnregisterServer+0x7b64
12 085af468 7824f516 fffffffe 781f2c2e 0000001c mfc80!_AfxDispatchCall(<function> * __formal = 0x40b59c84, void * __formal = 0x085af6b8, unsigned int __formal = 0x85a0003)+0x10 (CONV: stdcall) [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\olecall.cpp @ 40]
13 085af470 781f2c2e 0000001c 7824f49b 00000008 mfc80!CCmdTarget::CallMemberFunc(struct AFX_DISPMAP_ENTRY * pEntry = 0x6d756e20, unsigned short wFlags = 0x6562, struct tagVARIANT * pvarResult = 0x20202020 Empty, struct tagDISPPARAMS * pDispParams = 0x2a2a2a2a, unsigned int * puArgErr = 0x2a2a2a2a)+0x1ad (CONV: thiscall) [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\oledisp1.cpp @ 1064]

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

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

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

Вот мои возможные мысли, если файлы дампа на самом деле не являются причиной проблемы:

  • Другой процесс (не прикрепленный на моем adplus) вызвал перезапуск.
  • Полные дампы исключений второго шанса просто не генерируются.
  • Другие (есть мысли?)

PS: Извините, если я не указал некоторые детали, примеры кода и т. Д., Поскольку это конфиденциально. Я приложил все усилия, чтобы объяснить проблему, не ставя под угрозу политику компании.

Заранее спасибо!

1 ответ

Решение

Эта статья MSDN о диспетчеризации исключений объясняет процесс:

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

  1. Если процесс отлаживается, система уведомляет отладчик. Для получения дополнительной информации см. Обработка исключений отладчика.
  2. Если процесс не отлаживается или связанный с ним отладчик не обрабатывает исключение, система пытается найти обработчик исключений на основе фреймов путем поиска фреймов стека потока, в котором произошло исключение. Система сначала ищет текущий кадр стека, а затем просматривает предыдущие кадры стека в обратном порядке.
  3. Если не найден ни один обработчик на основе фреймов, или нет обработчика на основе фреймов, который обрабатывает исключение, но процесс отлаживается, система уведомляет отладчик во второй раз.
  4. Если процесс не отлаживается или связанный с ним отладчик не обрабатывает исключение, система обеспечивает обработку по умолчанию на основе типа исключения. Для большинства исключений действием по умолчанию является вызов функции ExitProcess.

На шаге 1 исключение называется исключением первого шанса, потому что это первый шанс, который любой может поймать и обработать исключение.

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

Только если процесс переходит к шагу 4, программа завершится сбоем или завершится. Поэтому да, только второстепенные исключения могут привести к сбою процесса.

Может ли неуправляемое исключение первого шанса вызвать сбой / перезапуск?

Смотрите раньше.

При расследовании аварии должен ли я расследовать только вторые случайные исключения?

В основном да. Это то, что все (>90%) делают при анализе сбоев.

В каких случаях мне также нужно исследовать дамп исключений первого шанса?

Случай 1:

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

Пример кода для такого сценария:

SomeObject o = null;
try {
    throw new Exception("First chance"); // consider this in some method
    o = new SomeObject();
}
catch (Exception)
{
    // make sure that the exception does not become a second chance exception
}
o.DoSomething(); // causes NullReferenceException first chance and second chance if uncaught

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

Случай 2:

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

Другие вопросы по тегам