C libsigsegv并响应堆栈溢出
我们正在尝试测试学生代码,为了使过程自动化,我们希望检测学生代码是否溢出堆栈 我在使用libsigsegv库及其相应的stackoverflow_install_处理程序时取得了一些成功。它工作得非常出色,直到学生的代码两次刷新堆栈 例如,以下是一些示例输出:C libsigsegv并响应堆栈溢出,c,stack-overflow,signals,segmentation-fault,C,Stack Overflow,Signals,Segmentation Fault,我们正在尝试测试学生代码,为了使过程自动化,我们希望检测学生代码是否溢出堆栈 我在使用libsigsegv库及其相应的stackoverflow_install_处理程序时取得了一些成功。它工作得非常出色,直到学生的代码两次刷新堆栈 例如,以下是一些示例输出: [# ~]$ ledit ./interpreter -> (use solution) -> (fun 1 2) *** Stack overflow detected *** -> (fun 1 2) Signal
[# ~]$ ledit ./interpreter
-> (use solution)
-> (fun 1 2)
*** Stack overflow detected ***
-> (fun 1 2)
Signal -10
[# ~]
初始“*检测到堆栈溢出*”是理想的输出。在第二次清理堆栈之后,我得到的只是一个无用的“信号-10”,程序停止执行。我希望再次看到stack overflow detected消息,并让代码继续执行
在我的堆栈溢出处理程序中,我只是将溢出检测消息打印到stderr,然后在解释器中跳回“等待输入状态”
谢谢你的帮助
编辑
根据下面caf的建议,我们添加了一个对sigsegv_leave_handler()的调用,如下所示:
但是,输出仍然是一样的。您是否遵循了本手册中的警告 …处理程序必须确保恢复 正常信号屏蔽(因为很多 处理程序运行时,信号被阻止 执行),并且还必须调用
sigsegv\u leave\u handler()
传送
控制那么只有它才能长JMP
走开
仅仅远离堆栈溢出并不一定足够。我还没有看到您将其嵌入的解释器的源代码,但我的直觉是堆栈溢出会导致某些内部解释器状态损坏,从而可能导致另一次崩溃。特别要注意的是,您得到的信号是SIGBUS(10),而不是SIGSEGV(11) 想象一下下面的场景:当解释器调用时,您刚好缺少堆栈溢出 <代码>malloc。Malloc修改一些内部数据,然后调用一个helper函数。堆栈溢出发生,您将jmp拖回解释器主循环。您的malloc池现在已损坏,您对此无能为力
我建议在检测到堆栈溢出时终止并重新启动解释器。或者,准确地找出解释器状态是如何被破坏的,并安排它成为一个较少的问题(这可能相当困难!)。您还可以在解释器中使用显式堆栈深度检查,而不是捕获SIGSEGV;这将允许您在SIGSEGV强制解决问题之前,在安全点处理错误。尝试更密切地遵循libsigsegv包中的示例代码。此示例代码不支持捕获一行中的两个连续堆栈溢出。特别是:
- 在延续中使用longjmp,而不是siglongjmp
- 在调用sigsegv_leave_处理程序之前,先调用sigprocmask
static void continuation(void *arg1, void *arg2, void *arg3) {
(void)(arg1);
(void)(arg2);
(void)(arg3);
siglongjmp(errorjmp, 1);
}
static void handler(int emergency, stackoverflow_context_t context) {
(void)emergency;
(void)context;
fprintf(stderr, "\n*** Stack overflow detected ***\n");
fflush(stderr);
sigsegv_leave_handler(continuation, NULL, NULL, NULL);
}