最近读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);
}