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