C 抓住机遇,继续生活
我正在写一个程序来检查它自己的地址空间 具体来说,我关心所有malloc-ed数据块。如果有一些系统调用来获取它们的列表,那就太棒了(对于我的应用程序,我不能使用LD_PRELOAD,-wrap,也不能使用任何额外的命令行选项)。如果有办法做到这一点,我更愿意听到它,而不是下面我所说问题的答案 与此相反,我目前的方法是取消对所有内容的引用并四处查看。显然,所有可能的指针集都是等待发生的segfaults雷区,因此我尝试注册一个信号处理程序并使用setjmp/longjmp(简单地通过让处理程序什么都不做来忽略segfault是一个无限循环,因为处理程序将返回故障指令)。一些示例代码如下所示:C 抓住机遇,继续生活,c,memory,malloc,signals,C,Memory,Malloc,Signals,我正在写一个程序来检查它自己的地址空间 具体来说,我关心所有malloc-ed数据块。如果有一些系统调用来获取它们的列表,那就太棒了(对于我的应用程序,我不能使用LD_PRELOAD,-wrap,也不能使用任何额外的命令行选项)。如果有办法做到这一点,我更愿意听到它,而不是下面我所说问题的答案 与此相反,我目前的方法是取消对所有内容的引用并四处查看。显然,所有可能的指针集都是等待发生的segfaults雷区,因此我尝试注册一个信号处理程序并使用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块)?sigsetjmp/siglongjmp有什么问题?为什么需要重置信号?]
signal()
是一个遗留接口,并且根据操作系统的不同,在信号处理器被调用后可以重新注册,也可以不重新注册;您可能需要发出另一个signal()
调用,将信号处理程序重置为处理程序中的最后一个操作。参见man 2信号
sigaction()
是设置信号处理程序的首选机制,因为它具有定义良好的可移植行为。当调用SIGSEGV
的信号处理程序时,SIGSEGV
信号将被屏蔽,就像被sigprocmask
屏蔽一样。这对于任何信号都是正确的。通常,从信号处理程序返回将取消它的掩码,但由于您不返回,因此这种情况永远不会发生。有两种可能的解决方案:
- 您可以在
之前或之后调用longjmp
,自行解除对其的屏蔽sigprocmask
- 您可以使用
安装信号处理程序(无论如何,这是首选的安装方式),并使用sigaction
标志防止其被屏蔽SA_NODEFER
- 您可以使用
和sigsetjmp
函数,这些函数本身负责保存和恢复信号掩码siglongjmp
sigaction
存在的原因。我选择sigaction是因为它使用起来更简单,但您完全正确:可移植性对于定义的行为很重要。不过,在本例中,问题最终是我没有用sigrelse清除信号,所以这不是问题所在。您不能在运行时使用LD_PRELOAD或类似的方法,但是由于您正在编译代码,您不能简单地定义自己的malloc()
,这是有原因的吗,或者在链接时包含其中一个?使用glibc的“内存分配挂钩”,您可以非常轻松地完成所需的检测: