簡體   English   中英

調用堆棧溢出時如何打印調用堆棧?

[英]How to print call stack when call stack overflows?

捕獲信號時,我使用以下代碼來打印調用堆棧。 但似乎它不適用於堆棧溢出錯誤。 經過一些實驗,我發現此問題可能是由backtrace的調用引起的。 我該如何解決?

#include <stdlib.h>
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>

void signal_handler(int sig)
{
  printf("signal: %d\n", sig);

  void* dump_array[256];
  int num = backtrace(dump_array, 256);

  if (num) 
  {
    printf("backtrace rank = %d\n", num);

    char** symbols = backtrace_symbols(dump_array, num);
    if (symbols) 
    {
      for (int i = 0; i < num; i++)
        printf("%s\n", symbols[i]);

      free(symbols);
    }
  }

  exit(-1);
}

void func()
{
  func();
}

int main(void)
{
  stack_t ss = {};
  ss.ss_size = SIGSTKSZ;

  if (!(ss.ss_sp = malloc(SIGSTKSZ)))
  {
    perror("malloc");
    exit(-1);
  }

  if (sigaltstack(&ss, NULL) == -1)
  {
    perror("sigaltstack");
    exit(-1);
  }

  struct sigaction act = {};
  act.sa_handler = signal_handler;
  act.sa_flags = SA_ONSTACK;
  sigfillset(&act.sa_mask);

  if (sigaction(SIGSEGV, &act, NULL) == -1)
    perror("sigaction");

  *(int*)123 = 456; // works
  //func(); // doesn't work

  return 0;
}

處理處理程序捕獲的堆棧溢出的常見解決方案是使用非常特定於編譯器的代碼在循環中進行回溯。 換句話說,沒有函數調用包括printf("signal: %d\\n", sig);

預防措施會限制反向跟蹤的數量。

signal_handler()一部分, signal_handler()檢測到重入signal_handler()時以不同方式處理事物。 也許使用static int first_time標志。

void signal_handler(int sig) {
  static int first_time = 0;
  if (first_time == 0) {
    first_time++;
    for (int i = 0; i<max; i++) {
      ... // gather back trace data
    }
  }
  ... // save exit into some place
  exit -1;
}

通常,答案非常依賴於編譯器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM