C libsigsegv并响应堆栈溢出

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

我们正在尝试测试学生代码,为了使过程自动化,我们希望检测学生代码是否溢出堆栈

我在使用libsigsegv库及其相应的stackoverflow_install_处理程序时取得了一些成功。它工作得非常出色,直到学生的代码两次刷新堆栈

例如,以下是一些示例输出:

[# ~]$ 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

+1仅用于使用buzzword+1尝试使用StackOverflow检测堆栈溢出感谢您的建议---我们尝试过,输出仍然相同。我修改了我原来的问题以反映这一点。(如果我没有遵守Stackoverflow惯例,我很抱歉,这是我第一次在这里提交问题。)鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久脱机。好吧,我说过这是libsigsegv包中的示例代码。我总结了这一联系中最重要的两点。你还想要什么?
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);                         
}