【发布时间】:2010-01-11 19:04:41
【问题描述】:
我正在尝试使用 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)
有什么想法吗?
谢谢。
【问题讨论】:
标签: c gdb garbage-collection