Call Stack information and exceptions

Started by
13 comments, last by Shannon Barber 22 years, 3 months ago
The dbghelp library doesn''t give very accurate results in release mode because of compiler optimizes away stack frames.

I believe the unreal uses their own push pop system. The Tips of the day at Flipcode has several of such systems.
Advertisement
quote:Original post by Void
The dbghelp library doesn''t give very accurate results in release mode because of compiler optimizes away stack frames.

doh!

- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
That''s not entirely true. Yes, the compiler optimizes the hell out of the release binary, but the [release] symbols will still provide you with a stack dump. Having the program create a minidump is actually a great way to do it. Then you can get the minidump, open it in windbg (with your copy of the symbols), and debug it (get the stack trace, etc). I believe creating a minidump is *very* simple (what, one API call?).


-Brannon
-Brannon
Unreal''s system is done "manually" via macros, as mentioned above. This has its strengths and weaknesses. Personally, I prefer automated stack dumps when possible (like with DbgHelp on Win32).

I haven''t had many problems getting accurate stack dumps from release builds compared to debug builds, for the most part. Unfortunately, there are still a handful of issues that I don''t believe even the "Under the Hood" column or "Debugging Applications" book mentions, in terms of the StackWalk function.

For the context information passed into StackWalk, I''ve seen some examples which use GetThreadContext(). I haven''t had a whole lot of luck with this function personally, since the fact that it''s deeper inside Win32 affects the resulting context, and you have to filter out the lower calls manually. Even then, the context I got back didn''t seem to be accurate many times. So I would recommend writing your own __declspec(naked) context retrieval function instead.

Once you know your context is correct, StackWalk''s addresses are based on the return addresses stored on the stack, which are not really the "call" instructions but rather the instruction afterward. This distinction often results in line number information that is one or more lines off of the actual line you''re currently in (it''s reporting the line number connected to the instruction after the call, not the one making the call). This is a problem at the top of the stack too, since EIP will already be an instruction beyond the one that crashed. Now, while it''s difficult to deal with the TOS being off by a line or so (it''s usually close enough in practice), the other stack elements always follow "call" instructions so they''re easy to correct. MSVC always uses a 5-byte call instruction form, so for all StackWalk results other than the TOS, subtract 5 bytes from what it returns. This will move the instruction addresses from the instruction after the "call" back onto the "call" itself. This slight change has given me much more accurate stack dumps in many situations.
In case anyone cares, here''s my report on implementing Houdini''s method in my engine''s debug code. It works well, but their''s one gotcha. You have to keep in mind that multiple threads will mess with the results unless you keep them away from each other in seperate lists (which isn''t that hard, once you realize it ).

[Resist Windows XP''s Invasive Production Activation Technology!]

This topic is closed to new replies.

Advertisement