On Tuesday 15 August 2000 you wrote:
Oh, I can’t:
- To much code to traverse.
Reasonable, though it is a powerful technique when absolutely nothing
else is working.
The C runtime WinMain/DllMain is actually fairly straightforward once
you’ve deciphered it. A bigger problem is that the static initializer
code is compiler-generated (no source) so you get dumped into
disassembly mode a lot - not everyone’s cup of tea.
- I have to idea where it fails
Ah. I thought you knew the point of failure and just couldn’t
breakpoint before it to step through. Fair enough.
In Unix, you get a signal (like: SEGV or BUS) and can trap it anytime to
browse process stack.
Under Win32 you have Structured Exception Handling (SEH) which fills
much the same role as UNIX signals. Each SEH exception has a unique
32-bit code. The equivalent of SIGSEGV is STATUS_ACCESS_VIOLATION
(0xc0000005). (The symbols STATUS_* are defined in WINNT.H.)
Every time an SEH exception is raised you will see a status line
appear in the Developer Studio output window, similar to “First-chance
exception in myprog.exe: 0xC0000005: Access Violation.”. This happens
regardless of any further processing. (0xe04d5343 is the code used by
the MSVC++ throw statement: all throws of C/C++ objects appear as this
SEH code. Interestingly, a C++ catch(type) statement will *only* catch
this SEH code, but a C++ catch(…) statement will catch all
recoverable SEH exceptions, even things like STATUS_ACCESS_VIOLATION.)
If there is a handler installed, then by default it is called and
devstudio takes no further action. If there is no handler installed,
then devstudio will automatically breakpoint. Unfortunately the C
runtime protects static initializer code with a catch-all handler to
ensure graceful termination in that case.
Actually, that fires off a warning bell to do with the code I posted
previously: if a catch-all handler is installed, DebugBreak() may not
work since hard-coded breakpoints are themselves implemented as SEH
exceptions (STATUS_BREAKPOINT, code 0x80000003). The following works
around this, and is necessary for Explorer extensions, some COM
servers, and almost certainly for debugging C runtime startup code:
#pragma init_seg(compiler)
class CBreak { public: CBreak() {
__try { DebugBreak(); }
__except(UnhandledExceptionFilter(GetExceptionInformation())){}
} } initBreak;
#pragma init_seg(user)
You can tell devstudio to *always* breakpoint on a particular
exception by going into Debug->Exceptions…, selecting the exception
that is causing the problem and choosing Stop Always (instead of Stop
if not handled).
The problem here is that this menu is only available during execution
of the debuggee - tricky if you can’t even get to the first line of the
program because of crashes in the startup code!
What you may have to do, is use my code snippet anyway, to force a
breakpoint before static initialization. Then choose
Debug->Exceptions…, Stop Always on the exception that is causing you
problems (probably 0xc0000005, it usually is), then continue
execution. You should now get a breakpoint at the point of failure.
On NT, the situation is quite different… Is there anything that I can
always stop at during program exit, regardless its’ exit state???
Not *every* program exit, no. Most crashes, yes, since they tend to
raise STATUS_ACCESS_VIOLATION a lot of the time. If you have heap
debugging turned on then certain memory corruptions automatically
raise STATUS_BREAKPOINT.
You can attempt to stop at program exit by setting a breakpoint on the
ExitProcess Win32 API, but this is tricky since you i) need to find
its entry-point address, which is different for different
service-packs and operating systems, ii) may not give you a complete
stack backtrace in the case of abnormal termination or if you don’t
have the necessary symbol files installed, and iii) not all process
exits run through ExitProcess (you may want to break on
TerminateProcess, ExitThread, TerminateThread et al.), just most of
them, and they’re not all even initiated within the process that is
dying.
So you generally have to tailor your technique to the particular type
of bug/crash that is occuring.
John
you gave me something that i could touch in a world where i’d had too much
something i could feel with my broken hands full of lost ideals but soon i’m
returning to you my friend and we’ll go where the rivers end in the silver sea
and i’ll carry you if you carry me