我正在编写一个程序来检查它自己的地址空间。
具体来说,我关心所有 malloc 的数据 block 。如果有一些系统调用来获取它们的列表,那就太棒了(对于我的应用程序,我不能使用 LD_PRELOAD、-wrap 或任何额外的命令行选项)。如果有办法做到这一点,我更愿意听到它,而不是下面我所说的问题的答案。
取而代之的是,我当前的方法是取消引用所有内容并环顾四周。显然,所有可能的指针的集合是等待发生的段错误的雷区,因此我尝试注册一个信号处理程序并使用 setjmp/longjmp (通过使处理程序什么也不做来简单地忽略段错误是一个无限循环,因为处理程序将返回错误指令)。一些示例代码如下所示:
static jmp_buf buf;
void handler(int i) {
printf(" Segfaulted!\n");
longjmp(buf,-1);
}
void segfault(void) {
int* x = 0x0;
int y = *x;
}
void test_function(void) {
signal(11,handler);
while (1) {
if (setjmp(buf)==0) {
printf("Segfaulting:\n");
segfault();
}
else {
printf("Recovered and not segfaulting!\n");
}
printf("\n");
}
}
输出为:
Segfaulting:
Segfaulted!
Recovered and not segfaulting!
Segfaulting:
Segmentation fault
因此,处理程序第二次无法工作。我不知道这是为什么,但我推测这与未清除原始信号有关。我不知道该怎么做。
顺便说一句,我首先尝试了 sigsetjmp/siglongjmp,但由于某种原因它们没有在 setjmp.h 中定义。我有一种模糊的感觉,需要传递一些额外的编译标志,但是,和以前一样,这个应用程序不允许这样做。
所使用的系统是 Ubuntu Linux 10.04 x86-64,任何解决方案都不需要是可移植的。
[编辑:处理程序中的 sigrelse 清除信号,并有效修复问题。现在的问题涉及提出的其他问题——是否有更好的方法(即获取 malloc block )? sigsetjmp/siglongjmp 是怎么回事?为什么需要重置信号?]
最佳答案
signal()
是一个遗留接口(interface),在调用信号处理程序后可能会也可能不会重新注册,具体取决于操作系统;您可能需要发出另一个 signal()
调用来将信号处理程序重置为处理程序中的最后一个操作。请参阅man 2 signal
。
sigaction()
是设置信号处理程序的首选机制,因为它具有明确定义和可移植的行为。
关于捕获分段违规并继续生活,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10307739/