例如,可以捕获SIGABRT并以longjump继续程序。
我想知道当我总是调用调用abort()的函数时,这是否会导致堆栈溢出。
我需要知道,因为我想在单元测试中使用断言宏(taht调用abort)。如果断言失败,我想继续进行下一次单元测试。
答案 0 :(得分:2)
abort
不需要清除堆栈; longjmp
将“清除”它,因为它会将堆栈指针重新回到setjmp
的位置。如果一切正确,重复调用longjmp
和setjmp
将不会导致堆栈溢出。
但是,longjmp
将跳过正常的执行路径,这可以自行调用资源泄漏。请考虑以下代码:
char *s = malloc(...);
... use s ...
free(s);
如果“... use s ...”部分调用某些longjmp
代码中的函数,free
将无法被调用,您将泄漏。这同样适用于关闭打开文件,套接字,释放共享内存段,收获分叉子项等等。
因此{C}编程很少使用longjmp
。如果你不想退出计划,我的建议是避免assert
。只需在单元测试中使用另一个宏,或切换到提供一个宏的测试框架。
答案 1 :(得分:1)
longjmp不会展开堆栈,但会修改堆栈指针:
如果调用setjmp的函数返回,则不再 可以安全地使用longjmp和相应的jmp_buf对象。 这是因为当函数时堆栈帧无效 回报。 调用longjmp恢复堆栈指针,因为 返回的函数将指向一个不存在的函数 覆盖/损坏的堆栈帧。
答案 2 :(得分:1)
假设POSIX,调用longjmp
退出由SIGABRT
引发的abort
是有效的,因为abort
被指定为异步信号安全(并且还因为这个信号不是异步的)。 (在简单的C中,几乎所有来自信号处理程序的东西都是UB,所以它通常不是一个有趣的案例。)但是,你有责任确保你自己的程序都没有。#39 ; s状态因此不一致,这样会导致程序在程序流程中立即或稍后以其他方式调用UB。
话虽如此,我同意user4815162342您的提案是一种非常糟糕的错误处理形式。如果您不想中止,请不要致电abort
,而是编写自己的错误处理功能。