Runtime call stack dump
I can think that many of you got to a point in programming when something goes wrong, but you don’t even know where to start. It all looks fine, but it still doesn’t so the stuff that it’s suppose to. For this reason we have the debugger, to help us in getting insight on the program(s) that we are trying to realize.
From experience I figured that with the debugger it is sometimes very hard to find the trouble maker and for that I deeply encourage the use of a logger in each program.
This post is not related to the logging system and how it should be done, but it is related to the possibility of dumping the call stack of all the active threads from your application (process).
This comes in handy when you have a situation that is triggered only in certain scenario and to simulate this within the debugger is very difficult. The solution in this case is the logging of the running threads and their state during runtime.
The advantages for this are far more than the old step by step debugging:
- You get you result (call stack of the running threads) faster
- You can investigate this at a later step
- Handling very special situations that require complex scenarios is more easily reproduced/traced using this system
I will leave here a sample (C++) on how this is available. Unfortunately this will only work on Windows and with an IDE greater than VS 5. The original version is from CodeProject and there are some small tweaks that I have added.
This is just a portion of the sample, related to the parsing of all the process threads.
class MyStackWalker : protected StackWalker
{
FILE * fout_;
public:
MyStackWalker() : StackWalker(), fout_ (0) {}
BOOL ShowCallstack( DWORD dwOwnerPID = GetCurrentProcessId())
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( FALSE );
if( !Thread32First( hThreadSnap, &te32 ) )
{
CloseHandle( hThreadSnap );
return( FALSE );
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if( te32.th32OwnerProcessID == dwOwnerPID )
{
StackWalker::ShowCallstack(OpenThread(READ_CONTROL,FALSE,te32.th32ThreadID));
}
} while( Thread32Next(hThreadSnap, &te32 ) );
CloseHandle( hThreadSnap );
return( TRUE );
}
};
You can find the full source code here.
Recent comments