子进程中的GDB回溯

9

我有一个应用程序,它分叉出一个子进程。

子进程执行一些操作,在执行过程中会出现分段错误。我使用了GDB进行调试,使用了以下命令:

set follow-fork-mode child

我还将子函数设为断点,但GDB没有在我的断点处暂停。
另外,父进程处理了段错误,所以我不得不使用ctrl-c退出。然后,当我使用backtrace打印栈时,我得到的只是“无栈”。
为什么断点没有被设置,而且我为什么没有得到堆栈?

不,但我有源代码。 - broun
你能从源代码中构建它(子程序)以调试模式吗? - sirgeorge
1
GNU gprof是用于性能分析而不是调试的。我(仍然)假设您想找出子进程在哪里终止,而不是对其进行性能分析。要以调试模式重新构建它,您应该在执行configure之前在您的shell(bash)中执行export CFLAGS=-g(我假设您知道如何从源代码构建程序)。我曾经对子进程进行了大量调试,但我无法回忆起一种情况,即gdb中的follow-fork-mode按预期工作而没有给我带来麻烦,因此我正在尝试为您提供一个解决方法。 - sirgeorge
1
  1. 找到您的子程序的“main”函数并在其中添加无限循环:volatile int iHang=1; while(iHang);
  2. 再次构建它
- sirgeorge
1
附着到无限循环中运行的子进程:gdb -p <child'd-pid>。然后在gdb中执行:set iHang=0。然后(同样在gdb中)执行:handle SIGSEGV stop。这样你就能够准确地看到你的子进程何时崩溃了。 - sirgeorge
显示剩余7条评论
1个回答

14
为什么断点没有被设置?
断点确实已经被设置了,但是它没有被触发,因为...你显然在调试错误的进程。
使用 "set follow-fork-mode child" 命令,GDB 将跟踪您创建的第一个子进程。也许您创建了多个子进程?
解决此问题的一种方法是使用 signal 或 sigaction 建立 SIGSEGV 处理程序。
在处理程序中,执行以下操作:
void handler(int signo)
{
  int i = 1;
  fprintf(stderr, "pid=%d, got signal=%d\n", getpid(), signo);
  while (i) { }
}

一旦你在另一个窗口看到消息被打印出来:

 gdb /proc/<pid>/exe <pid>
 (gdb) where

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接