4

我只是想知道如何报告分段错误。

  • 该进程将直接死亡,因此显然它无法报告它。
  • 除非进程传递信号,否则 shell 将无法确定,这可能不一定是这种情况。
  • 操作系统可能可以做某事,但我不确定如何做。

其中哪一个报告了分段错误(只是一个示例),以及如何报告?

4

4 回答 4

3

该进程将直接死亡,因此显然它无法报告它。

这实际上是错误的。可以安装一个处理程序来替换默认的处理程序,它只是转储核心并死掉SIGSEGV预加载库可以这样做以捕获分段违规并使用可用的有限设施来通知在系统上运行的另一个进程在退出之前发生了什么。

于 2012-09-03T01:50:09.353 回答
2

You can have some code like this which will call the GDB command to dump the call trace:

void BacktraceOnSegv() {
  struct sigaction action = {};
  action.sa_handler = DumpBacktrace;
  if (sigaction(SIGSEGV, &action, NULL) < 0) {
    perror("sigaction(SEGV)");
  }
}

void DumpBacktrace(int) {
  pid_t dying_pid = getpid();
  pid_t child_pid = fork();
  if (child_pid < 0) {
    perror("fork() while collecting backtrace:");
  } else if (child_pid == 0) {
    char buf[1024];
    sprintf(buf, "gdb -p %d -batch -ex bt 2>/dev/null | "
            "sed '0,/<signal handler/d'", dying_pid);
    const char* argv[] = {"sh", "-c", buf, NULL};
    execve("/bin/sh", (char**)argv, NULL);
    _exit(1);
  } else {
    waitpid(child_pid, NULL, 0);
  }
  _exit(1);
}

Here is an implementation that support more platforms.

于 2012-09-03T02:41:21.713 回答
2

如果您查看函数wait()waitpid(),您会发现退出状态中的一位表示核心转储。POSIX 规范提到WIFSIGNALED[原文如此] 并 WTERMSIG获取终止进程的信号。POSIX 规范没有提到它,但在 Mac OS X (10.7.4) 上,例如,有一个WCOREDUMP()宏来测试是否创建了核心文件。

于 2012-09-03T01:53:52.500 回答
1

好的,首先,当 CPU 尝试访问进程无权访问的地址时,会发生分段错误。在最低级别,内存映射的实现必须检测到这一点,这通常会产生中断。内核接收到该中断,并有一个其他代码段的地址表,每个代码段都旨在处理该中断。

当内核接收到该中断时,它将其转换为特定值(我含糊其辞,因为确切的细节因硬件架构和内核实现而异)。 SIGSEGV通常定义为值 11,但确切的值并不重要;它定义在signal.h.

此时,信号值被传递到内核内部的另一个表,其中包含“信号处理程序”的地址。这些处理程序之一位于由 表示的偏移量处SIGSEGV。除非您已对其进行了更改,否则该地址通常是导致核心转储的例程,假设适当的限制允许,但您可以将其替换为您自己的例程的地址,它可以做任何您喜欢的事情。

于 2012-09-03T02:51:32.270 回答