I'm currently looking for a way to get backtrace information under Windows, from C code (no C++).
I'm building a cross-platform C library, with reference-counting memory management. It also have an integrated memory debugger that provides informations about memory mistakes (XEOS C Foundation Library).
When a fault occurs, the debugger is launched, providing information about the fault, and the memory record involved.
On Linux or Mac OS X, I can look for execinfo.h
in order to use the backtrace
function, so I can display additional infos about the memory fault.
I'm looking for the same thing on Windows.
I've seen How can one grab a stack trace in C? on Stack Overflow. I don't want to use a third-party library, so the CaptureStackBackTrace
or StackWalk
functions looks good.
The only problem is that I just don't get how to use them, even with the Microsoft documentation.
I'm not used to Windows programming, as I usually work on POSIX compliant systems.
What are some explanations for those functions, and maybe some examples?
EDIT
I'm now considering using the CaptureStackBackTrace
function from DbgHelp.lib
, as is seems there's a little less overhead...
Here's what I've tried so far:
unsigned int i;
void * stack[ 100 ];
unsigned short frames;
SYMBOL_INFO symbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
for( i = 0; i < frames; i++ )
{
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, &symbol );
printf( "%s\n", symbol.Name );
}
I'm just getting junk. I guess I should use something else than SymFromAddr
.
Alright, now I got it. : )
The problem was in the SYMBOL_INFO structure. It needs to be allocated on the heap, reserving space for the symbol name, and initialized properly.
Here's the final code:
void printStack( void );
void printStack( void )
{
unsigned int i;
void * stack[ 100 ];
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
for( i = 0; i < frames; i++ )
{
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
printf( "%i: %s - 0x%0X\n", frames - i - 1, symbol->Name, symbol->Address );
}
free( symbol );
}
Output is:
6: printStack - 0xD2430
5: wmain - 0xD28F0
4: __tmainCRTStartup - 0xE5010
3: wmainCRTStartup - 0xE4FF0
2: BaseThreadInitThunk - 0x75BE3665
1: RtlInitializeExceptionChain - 0x770F9D0F
0: RtlInitializeExceptionChain - 0x770F9D0F