簡體   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