下面的代码在第二个printf
处有分段错误,而这需要处理(setjmp
)请注意,每个printf
由于格式字符串错误而创建分段错误第一个分段错误被正确处理,而不是第二个(在注释掉printf
之后运行代码将不会分段错误)。
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
static jmp_buf escapeCallJmpBuf;
static void sigsegv_handler(int signal, siginfo_t *info, void *context) {
longjmp(escapeCallJmpBuf, 1);
}
int main(int argc, char **argv) {
struct sigaction segvAction, segvActionOld;
segvAction.sa_handler = 0;
memset(&segvAction.sa_mask, 0, sizeof(segvAction.sa_mask));
segvAction.sa_flags = SA_SIGINFO;
segvAction.sa_sigaction = sigsegv_handler;
sigaction(SIGSEGV, &segvAction, &segvActionOld);
int res;
// Catch first segmentation fault
if (setjmp(escapeCallJmpBuf)) {
res = 1;
} else {
printf ("%s\n", 2); // This will segfault
res = 0;
}
// try to catch second segmentation fault
if (setjmp(escapeCallJmpBuf)) {
res = 2;
} else {
printf ("%s\n", 3); // This will segfault
res = 0;
}
sigaction(SIGSEGV, &segvActionOld, 0);
return res;
}
最佳答案
setjmp
和longjmp
不一定恢复信号屏蔽(取决于实现)可能发生的情况是在处理第一个SIGSEGV之后,信号掩码恢复为默认值因此,第二个错误没有被捕获,也就是说,默认操作代替了你的动作,即退出进程。
你应该改用sigsetjmp
和siglongjmp
。
POSIX状态:
未指定longjmp()是还原信号掩码、保持信号掩码不变,还是还原为调用setjmp()时的值。
并建议:
其行为取决于信号掩码值的应用程序
不应使用longjmp()和setjmp(),因为它们对
未指定信号掩码,但应改为使用siglongjmp()
和sigsetjmp()函数(可以保存和恢复信号掩码
在应用程序控制下)。
此外,跳出信号处理程序也有一些限制:
建议应用程序不要调用longjmp()或
来自信号处理程序的siglongjmp()避免未定义的行为
从信号处理程序调用这些函数时,应用程序需要
确保以下两点之一:
在调用longjmp()或siglongjmp()之后,进程只调用
异步信号安全函数,不从初始调用返回
到main()。
处理程序调用longjmp()或siglongjmp()的任何信号都被阻止
每次调用非异步信号安全函数时
调用是在从初始调用返回到main()之后进行的。
关于c - SIGSEGV不能两次被抓获,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51765041/