Follow-up questions: "When investigating a crash, should I only investigate second chance exceptions? What are the cases when I also need to investigate a first chance exception dump?"
My questions are a bit broad but I'm curious to what's really the answer. I've read numerous articles that says first chance exceptions are unlikely to cause an application crash; it's a second chance exceptions that causes it. A simple google search doesn't answer my question directly.
EDIT: Here are sample articles, but there are many other more:
What is a First Chance Exception?:
"For code without exception handling, the debugger will receive a second chance exception notification and will stop with a unhandled exception. "
Program crashes, but Debug Diag says it's a first chance exception, is that correct?
Surely by definition, only a 2nd chance exception can make code crash, i.e. one that has NOT been handled by the code?
I'm having an intermittent issue where my app restarts or crash (no error in event viewer) but before it restarts, Adplus generates some first chance AccessViolation exceptions. No second chance exceptions.
Below is a snippet of the FULLDUMP_FirstChance_av_AccessViolation on 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
Sample call stacks below:
# 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]
The error are about heap corruptions and invalid pointers which I'm still studying about. I'm a complete newbie on heaps and mallocs and I just learned debugging using WinDbg. I just wanted to know if I'm wasting my time learning about memory allocations when it's not my priority and will not really fix my issue. (Of course knowing about heaps is a good thing but fixing the main issue is the top priority)
I'm confident in my adplus config file and I'm sure it will generate a full dumps on all second chance exceptions. I tried it on a sample application.
The app doesn't crash, it just unexpectedly and intermittently restart without event viewer error. It can be recreated intermittently when a specific service is used.
Here are my possible thoughts if the dump files are not really the cause of the issue:
PS: Sorry if I didn't specify some details and code samples, etc. as it's confidential. I did my best explaining the issue without compromising company policy.
Advance thank you!
This MSDN article about exception dispatching explains the process:
When an exception occurs in user-mode code, the system uses the following search order to find an exception handler:
- If the process is being debugged, the system notifies the debugger. For more information, see Debugger Exception Handling.
- If the process is not being debugged, or if the associated debugger does not handle the exception, the system attempts to locate a frame-based exception handler by searching the stack frames of the thread in which the exception occurred. The system searches the current stack frame first, then searches through preceding stack frames in reverse order.
- If no frame-based handler can be found, or no frame-based handler handles the exception, but the process is being debugged, the system notifies the debugger a second time.
- If the process is not being debugged, or if the associated debugger does not handle the exception, the system provides default handling based on the exception type. For most exceptions, the default action is to call the ExitProcess function.
In step 1 the exception is called a first chance exception, because it's the first chance anyone can catch and handle the exception.
In step 3 the same exception is called a second chance exception, because it's the second time, the debugger gets the chance to catch and handle the exception.
Only if the process continues to step 4 the program will crash or exit. Therefore yes, only second chance exceptions can crash a process.
Can unmanaged first chance exception cause a crash/restart?
No. See before.
When investigating a crash, should I only investigate second chance exceptions?
Basically yes. That's what everyone (>90%) does when analyzing crashes.
What are the cases when I also need to investigate a first chance exception dump?
Case 1:
That second chance exception might be a result of a previous first chance exception. Due to that first chance exception, a value might not be initialized and cause a different second chance exception.
Example code for such a scenario:
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
The application crashes because of a NullReferenceException but the real cause is the Exception before. However, such cases are typically easy to identify without having a look at first chance exceptions.
Case 2:
Exceptions have a high overhead, i.e. they cost CPU cycles and thus performance. If you have really many first chance exceptions, you might want to get rid of them.