c - gdb:为 SIGBUS 处理程序设置断点

标签 c gdb garbage-collection

我正在尝试使用 GDB 调试一个简单的停止复制垃圾收集器(用 C 语言编写)。 GC 通过处理 SIGBUS 来工作。我在 SIGBUS 信号处理程序的顶部设置了一个断点。我已经告诉 GDB 将 SIGBUS 传递给我的程序。但是,它似乎不起作用。

以下程序(内联解释)显示了我的问题的本质:

#include <stdio.h>
#include <sys/mman.h>
#include <assert.h>
#include <signal.h>

#define HEAP_SIZE 4096

unsigned long int *heap;

void gc(int n) {
  signal(SIGBUS, SIG_DFL); // just for debugging
  printf("GC TIME\n");
}

int main () {

  // Allocate twice the required heap size (two semi-spaces)
  heap = mmap(NULL, HEAP_SIZE * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED,
              -1, 0);
  assert (heap != MAP_FAILED);
  // 2nd semi-space is unreadable. Using "bump-pointer allocation", a SIGBUS
  // tells us we are out of space and need to GC.
  void *guard = mmap(heap + HEAP_SIZE, HEAP_SIZE, PROT_NONE, MAP_ANON |
                     MAP_SHARED | MAP_FIXED, -1, 0);
  assert (guard != MAP_FAILED);
  signal(SIGBUS, gc);
  heap[HEAP_SIZE] = 90; // pretend we are out of heap space
  return 0;
} 

我在 Mac OS X 10.6 上编译并运行该程序并获得我期望的输出:

$ gcc debug.c
$ ./a.out
GC TIME
Bus error

我想使用 GDB 运行和调试这个程序。特别是,我想在 gc 函数(实际上是 gc 信号处理程序)处设置一个断点。当然,我也需要告诉 GDB 不要在 SIGBUS 上停止:

$ gdb ./a.out 
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)
... snip ...
(gdb) handle SIGSEGV SIGBUS nostop noprint
Signal        Stop  Print   Pass to program Description
SIGBUS        No    No  Yes     Bus error
SIGSEGV       No    No  Yes     Segmentation fault
(gdb) break gc
Breakpoint 1 at 0x100000d6f

但是,我们永远不会到达断点:

(gdb) run
Starting program: /snip/a.out 
Reading symbols for shared libraries +. done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x0000000100029000
0x0000000100000e83 in main ()
(gdb) 

显然,没有调用信号处理程序(未打印 GC TIME)。此外,我们仍在 main() 中,在错误的 mov:

0x0000000100000e83 <main+247>:  movq   $0x5a,(%rax)

有什么想法吗?

谢谢。

最佳答案

在内部,错误的内存访问会导致 Mach 异常 EXC_BAD_ACCESS 被发送到程序。通常,这会转换为 SIGBUS UNIX 信号。然而,gdb 在信号转换之前直接拦截 Mach 异常。解决方案是在运行程序之前向 gdb 命令 set dont-handle-bad-access 1。然后使用正常机制,并接受信号处理程序中的断点。

关于c - gdb:为 SIGBUS 处理程序设置断点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2044179/

相关文章:

java - 使用多线程使垃圾收集器使用 100% 的 CPU 时间

c# - 在非托管异步操作期间保持对象事件

c++ - 为面向对象的 C++ 代码开发 C 包装 API

c - GDB 单步执行汇编并显示下一条将要执行的指令。

php - 禁用垃圾收集

c++ - 比较时出现段错误

c - 段错误回溯到 vfprintf?

c - 如何正确使用startup-ipi来启动应用处理器?

python - 为什么以下代码在 codechef 中给出段错误,但在其他地方却工作得绝对正确

c - C中并发数据结构的内存消耗