linux和hpux环境下程序崩溃堆栈打印

程序崩溃时打印堆栈信息,方便定位

  • 具体流程为:
    • 编译程序时生成map文件
    • 设置信号处理函数
    • 打印程序在系统中maps映射
    • 打印backtrace信息
    • raise信号
  • 也可以使用libunwind第三方库实现,该库最初在商业版hpux中提供,现在Linux平台下也可使用。利用这些调试信息来达到堆栈展开或者栈回溯的目的,则是libunwind做的事情。当然libunwind能做的也不仅仅局限于这些,利用libunwind还可以实现non-local goto和efficient setjmp 等。
  • 优点:
    • 系统未打开coredump时也能够捕获一些崩溃信息
    • gcc版本不一致时,借助map文件,能够定位程序崩溃堆栈点
//设置信号处理函数
int setup_sigsegv(int signum)
{
  struct sigaction action;

  memset(&action, 0, sizeof(action));
  action.sa_sigaction = signal_segv;
  action.sa_flags = signum;
  if (sigaction(signum, &action, NULL) < 0) {
  	return -1;
  }
  return 1;
}
#if defined(linux) || defined(__linux) || defined(__linux__)
void signal_segv(int signum, siginfo_t *info, void* ptr)
{
  void *bt[0x40];
  size_t sz;
  char buff[0xff] = { 0x00 };
  char filename[0xff] = { 0x00 };
  struct tm* tm_ptr = NULL;
  time_t t_time;

  time(&t_time);
  tm_ptr = localtime(&t_time);
  sprintf(filename,  "%s/%04d_%02d_%02d_%02d_%02d_%02d.dump",
  	getExePath().c_str(), //程序路径
  	tm_ptr->tm_year + 1900,
  	tm_ptr->tm_mon + 1,
  	tm_ptr->tm_mday,
  	tm_ptr->tm_hour,
  	tm_ptr->tm_min,
  	tm_ptr->tm_sec );
  printf("filename =%s\n", filename);

  sprintf(buff, "cat /proc/%d/maps >> %s", getpid(), filename);
  system((const char*)buff);


  int fd = open(filename, O_APPEND | O_RDWR);
  const char* const split = "-------------------------------------------------------------------\n";
  write(fd, "\n\n", 2);
  write(fd, split, strlen(split));
  sz = backtrace(bt, 0x40);
  backtrace_symbols_fd(bt, sz, fd);
  close(fd);
  signal(signum, SIG_DFL);
  raise(signum);
  }
  #endif
//hpux下利用系统自带libunwind.so库打印堆栈信息
//g++下直接调用_UNW_STACK_TRACE编译未通过,采取动态加载库方式
//gcc编译可以直接调用_UNW_STACK_TRACE,原因未知
#if defined(hpux) || defined(__hpux) || defined(__hpux__)
void signal_segv(int signum, siginfo_t *info, void* ptr)
{
  char filename[0xff] = { 0x00 };
  struct tm* tm_ptr = NULL;
  time_t t_time;

  time(&t_time);
  tm_ptr = localtime(&t_time);
  sprintf(filename,  "%s/%04d_%02d_%02d_%02d_%02d_%02d.dump",
  	getExePath().c_str(),
  	tm_ptr->tm_year + 1900,
  	tm_ptr->tm_mon + 1,
  	tm_ptr->tm_mday,
  	tm_ptr->tm_hour,
  	tm_ptr->tm_min,
  	tm_ptr->tm_sec );
  FILE* file = fopen(filename, "w+");
  void* plib = NULL;
  plib = dlopen("libunwind.so", RTLD_NOW | RTLD_GLOBAL);
  if (plib) {
  	typedef uint32_t (*STACK_TRACE_FILE)(FILE*);
  	STACK_TRACE_FILE func_trace = (STACK_TRACE_FILE)dlsym(plib, "_UNW_STACK_TRACE");
  	if (func_trace) {
  		func_trace(file);
  	}
  }
  fclose(file);
  signal(signum, SIG_DFL);
  raise(signum);
}
  • hpux下g++编译_UNW_STACK_TRACE未定义符号问题,见下篇

你可能感兴趣的:(c++编程)