我们正在尝试测试学生代码,为了使流程自动化,我们想检测学生代码是否溢出了堆栈。
我使用libsigsegv库及其相应的stackoverflow_install_handler取得了一些成功。它的运行非常出色,直到学生的代码两次将堆栈炸毁为止。
例如,这是一些示例输出:
[# ~]$ ledit ./interpreter
-> (use solution)
-> (fun 1 2)
*** Stack overflow detected ***
-> (fun 1 2)
Signal -10
[# ~]
初始的“ *检测到堆栈溢出* ”是理想的输出。第二次删除堆栈后,我得到的只是一个无用的“Signal -10”,程序停止执行。我想再次看到检测到堆栈溢出的消息,然后让代码继续执行。
在我的堆栈溢出处理程序中,我只是将溢出检测消息打印到stderr,并长时间跳回解释器中的“等待输入状态”。
谢谢你的帮助!
编辑
根据以下caf的建议,我们已经像下面这样添加了对sigsegv_leave_handler()的调用:
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);
}
但是,输出仍然相同。
最佳答案
仅仅远离堆栈溢出并不一定足够。我还没有看到要嵌入到其中的解释器的源代码,但是我的直觉是,堆栈溢出会使某些内部解释器状态损坏,这可能会导致再次崩溃。特别要注意的是,您收到的信号是SIGBUS(10),而不是SIGSEGV(11)。
想象以下情形:当解释器调用malloc
时,您只是堆栈溢出而已。 Malloc更改一些内部数据,然后调用辅助函数。发生堆栈溢出,并且您将longjmp返回到解释器主循环。您的malloc池现在已损坏,您无能为力。
我建议在检测到堆栈溢出时终止并重新启动解释器。或者,准确找出解释器状态如何损坏,并安排它减少问题的发生(这可能非常困难!)。您也可以在解释器中使用显式堆栈深度检查,而不是捕获SIGSEGV。这样您就可以在SIGSEGV强制执行此问题之前安全地处理错误。
关于c - libsigsegv并响应堆栈溢出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5013806/