backtrace on *nix and Windows
最近读OceanBase的源码,摘录一段错误诊断比较有用的代码:
//#define OCEAN_BTREE_CHECK
#ifdef OCEAN_BTREE_CHECK
#include <execinfo.h>
#define OCEAN_BTREE_CHECK_FALSE(cond, format, args...) if ((cond)) \
{ \
char _buffer_stack_[256]; \
{ \
void *array[10]; \
int i, idx=0, n = backtrace(array, 10); \
for (i = 0; i < n; i++) { \
idx += snprintf(idx+_buffer_stack_, 25, "%p,", array[i]); \
} \
} \
TBSYS_LOG(ERROR, "%s" format, _buffer_stack_, ## args); \
}
#define OCEAN_BTREE_CHECK_TRUE(cond, format, args...) \
OCEAN_BTREE_CHECK_FALSE(!(cond), format, ## args)
#else
#define OCEAN_BTREE_CHECK_TRUE(cond, format, ...)
#define OCEAN_BTREE_CHECK_FALSE(cond, format, ...)
#endif
其中关键就是用了backtrace* API。对于Windows下,此类工具代码在C++中可以由异常构建,但对于纯C代码,还是需要使用DbgHelp API的。找到的一个例子如下:
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);
}