例如,可以捕获SIGABRT并使用longjump继续程序。
我想知道当我始终调用调用abort()的函数时,这是否会导致堆栈溢出。
我需要知道这一点,因为我想在单元测试中使用assert宏(调用abort)。如果assert失败,我希望继续进行下一个单元测试。
例如,可以捕获SIGABRT并使用longjump继续程序。
我想知道当我始终调用调用abort()的函数时,这是否会导致堆栈溢出。
我需要知道这一点,因为我想在单元测试中使用assert宏(调用abort)。如果assert失败,我希望继续进行下一个单元测试。
abort
不需要清空堆栈;longjmp
会将堆栈指针倒回到 setjmp
的位置,从而“清空”堆栈。如果其他一切正确,反复调用 longjmp
和 setjmp
将不会导致堆栈溢出。
然而,longjmp
会跳过正常的执行路径,这可能会导致资源泄漏。考虑以下代码:
char *s = malloc(...);
... use s ...
free(s);
longjmp
,free
将没有机会被调用,你将会泄漏内存。同样的问题也适用于关闭打开的文件、套接字、释放共享内存段、回收fork出来的子进程等等。longjmp
。我的建议是,如果您不希望程序退出,请避免使用assert
。在您的单元测试中使用另一个宏,或者切换到提供其他宏的测试框架。longjmp不会展开堆栈,但它确实修改了堆栈指针:
如果调用setjmp的函数返回,则不再安全使用相应的jmp_buf对象调用longjmp。这是因为当函数返回时,堆栈帧将失效。调用longjmp会恢复堆栈指针,由于函数已经返回,因此堆栈指针将指向不存在且可能被覆盖/损坏的堆栈帧。
abort
引发的SIGABRT
信号可以通过调用longjmp
来跳出,这是有效的,因为abort
被指定为异步信号安全的(并且该信号不是异步的)。 (在普通的C语言中,从信号处理程序中执行几乎任何操作都是未定义行为,因此通常不是有趣的讨论案例。)但是,您需要确保没有留下任何导致程序状态不一致的痕迹,以便在程序流程中的其他时间立即或较晚地导致程序调用未定义行为。
话虽如此,我同意用户4815162342的观点,您的提案是一种非常糟糕的错误处理形式。如果您不想中止程序,请勿调用abort
,而应编写自己的错误处理函数。
assert
,但我认为这种方法在单元测试中并没有什么大问题,特别是对于某些类型的单元测试,你甚至可能会使用 SIGSEGV
来做同样的事情... - R.. GitHub STOP HELPING ICE