C异常处理机制:setjmp和longjmp
setjmp()和longjum()是通過操縱過程活動記錄實現的。它是C語言所獨有的。它們部分你不了C語言有限的轉移能力。這個兩個函數協同工作,如下所示:
??? *setjmp(jmp_buf j)必須首先被調用。它表示“使用變量j記錄現在的位置。函數返回零。”
??? *longjmp(jmp_buf j,int i)可以接著被調用。它表示“回到j所記錄的位置,讓它看上去像是從原來的setjmp()函數返回一樣。但是函數返回i,使代碼知道它實際上是通過longjmp()返回的。“坳口不?
??? *當使用longjmp()時,j的內容被銷毀。
??? setjmp保存了一份程序的計數器和當前的棧頂指針。如果喜歡也可以保存一些初始值。longjmp恢復這些值,有效的轉移控制并把狀態重置回保存狀態的時候。這被稱做“展開堆棧(unwinding stack)",因為你從堆棧中展開過程活動記錄,直到取得保存在其中的值。盡管longjmp會導致轉移,但它和goto又有不同,區別如下:
??? *goto語句不能跳出C語言當前的函數(這也是“longjmp”取名的由來,它可以跳的很遠,甚至可以跳到其他文件的函數中)。
??? *用longjmp只能跳回到曾經到過的地方。在setjmp的地方仍留有一個過程活動記錄。從這個角度講,longjmp更像是“從何處阿里(come from)“而不是”往哪里去(go to)”。longjmp接受一個額外的整型參數并返回它的值,這可以知道是由longjmp轉移到這里的還是從上條語句執行后自然而然來的這里的。
??? 下面的代碼顯示了setjmp()和longjmp()一例。
???? #include <stdio.h>
???? #include <setjmp.h>
???? jmp_buf buf;
?
???? banana() {
???????? printf("%s","in banana() \n");
???????? longjmp(buf,1);
???????? printf("%s","you will never see this \n");
???? }
?
???? int main() {
???????? if(setjmp(buf)) {
???????????? printf("%s","back in main\n");
???????? }
???????? else {
???????????? printf("%s","first time throught\n");
???????????? banana();
???????? }
???? }
??? 輸出結果如下:
??? first time throught
??? in banana()
??? back in main
??? 需要注意的地方是:保證局部變量在longjmp過程中一直保持它的值的唯一可靠方法是把它聲明為volatile(這使用于那些值在setjmp執行和longjmp返回之間會改變的變量)
??? setjmp/longjmp最大的用途是錯誤恢復。只要還沒有從函數中返回,一旦發現一個不可恢復的錯誤,可以把控制轉移到主輸入循環,并從那里重新開始。有些人使用setjmp/longjmp從一串無數的函數調用中立即返回。還有些人用它們防范潛在的危險代碼。
??? setjmp/longjmp在C++中演變為更普通的異常處理機制"catch"和"throw"。
總結
以上是生活随笔為你收集整理的C异常处理机制:setjmp和longjmp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我们都笑了freeeim
- 下一篇: 顺便抹了下眼眶的飞鸽传书官方网站