繁体   English   中英

C中的abort()函数是否清理堆栈?

[英]Does the abort() function in C clean the stack?

例如,有可能赶上SIGABRT并继续执行该程序,只需进行一次长跳。

我一直在调用调用abort()的函数时,不知道是否会导致堆栈溢出。

我需要知道,因为我想在单元测试中使用assert宏(taht调用中止)。 如果断言失败,我想继续进行下一个单元测试。

abort不需要清除堆栈; longjmp会“清除”它,因为它将堆栈指针退回到setjmp的位置。 如果其他所有方法都正确,则反复调用longjmpsetjmp不会导致堆栈溢出。

但是, longjmp将跳过正常的执行路径,这可能会自行调用资源泄漏。 考虑以下代码:

char *s = malloc(...);
... use s ...
free(s);

如果“ ... use s ...”部分从代码中调用了longjmp s的某些函数,则free不会有被调用的机会,并且您会泄漏。 这同样适用于关闭打开的文件,套接字,释放共享内存段,获取分叉的子对象等。

因此, longjmp很少在C编程中使用。 我的建议是,如果您不打算退出程序,请避免assert 只需在单元测试中使用另一个宏,或切换到提供该宏的测试框架即可。

longjmp不会展开堆栈,但是会修改堆栈指针:

如果返回了调用setjmp的函数,则不再可以安全地将longjmp与相应的jmp_buf对象一起使用。 这是因为函数返回时,堆栈帧无效。 调用longjmp将恢复堆栈指针 ,由于返回了函数,该指针将指向不存在的,可能会被覆盖/损坏的堆栈帧。

假定为POSIX,则调用longjmp来退出abort引发的SIGABRT是有效的,因为abort被指定为异步信号安全的(并且还因为该信号不是异步的)。 (在普通C语言中,从信号处理程序执行几乎所有操作都是UB,因此通常不应该谈论这个有趣的情况。)但是,您有责任确保自己程序的状态不会因此而保持不一致,在这种情况下一种使您的程序立即或在程序流程中更晚时间以其他方式调用UB的方式。

话虽如此,我同意user4815162342的建议,这是错误处理的一种非常糟糕的形式。 如果您不想中止,请不要调用abort ,而要编写自己的错误处理函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM