int setjmp(jmp_buf jmpb) 設定緩衝區來儲存堆疊的內容,將儲存的上下文存入程序的自身的資料空間(u區),並繼續在當前的上下文中執行,一旦碰到了longjmp,進城就從該程序 的u區,取出先前儲存的上下文,並恢復該程序的上下文為先前儲存的上下文。這時核心將使得程序從setjmp處執行(摘自:unix平台下c語言高階程式設計 指南)
setjmp和longjmp的函式原型在setjmp.h中。
函式原型:
int setjmp(jmp_buf envbuf);
setjmp函式用緩衝區envbuf儲存系統堆疊的內容,以便後續的longjmp函式使用。setjmp函式初次啟用時返回0值。
void longjmp(jmp_buf envbuf, int val);
longjmp函式中的引數envbuf是由setjmp函式所儲存的堆疊環境,引數val設定setjmp函式的返回值。longjmp函式本身是沒有返回值的,它執行後跳轉到儲存envbuf引數的setjmp函式呼叫,並由setjmp函式呼叫返回,此時setjmp函式的返回值就是val。
呼叫longjmp函式時不能使setjmp函式返回0,如果val為0,則setjmp函式返回1。longjmp函式從來不返回,因為它呼叫後就跳轉到setjmp函式儲存的堆疊處,恢復堆疊開始執行,所以longjmp函式不會返回。
void longjmp(jmp_buf jmpb, int val) 使程序返回到 setjmp處執行,retval 表示此時setjmp的返回值。
longjmp必須在setjmp呼叫之後,而且longjmp必須在setjmp的作用域之內。具體來說,在乙個函式中使用setjmp來初始化 乙個全域性標號,然後只要該函式未曾返回,那麼在其它任何地方都可以通過longjmp呼叫來跳轉到 setjmp的下一條語句執行。實際上setjmp函式將發生呼叫處的區域性環境儲存在了乙個jmp_buf的結構當中,只要主調函式中對應的記憶體未曾釋放 (函式返回時區域性記憶體就失效了),那麼在呼叫longjmp的時候就可以根據已儲存的jmp_buf引數恢復到setjmp的地方執行。
setjmp函式的返回值(直接返回時為0,longjmp跳轉返回時為longjmp的狀態引數retval,根據setjmp的返回值就可以判斷程式是 正常執行還是進行異常處理。
乙個setjmp可以有多個longjmp。 setjmp用於初始化跳轉變量(相當於打了乙個標記,宣告"用本跳轉變量的longjmp就跳到我這裡來啦"),longjmp用於跳轉。
setjmp可以多次返回,返回0表示初始化跳轉變量完成(也稱直接返回);返回其他值表示有函式呼叫了longjmp, 這時的返回值是longjmp設定的。 所以setjmp語句後有乙個switch-case塊,根據setjmp返回的不同值進行不同的處理。
setjmp()和longjum()是通過操縱過程活動記錄實現的。許多程式設計師新手(包括我-o-)並不知道這個強大的機制,因為它是c語言所獨有的。它們部分你不了c語言有限的轉移能力。這個兩個函式協同工作,如下所示:
*setjmp(jmp_buf j)必須首先被呼叫。它表示「使用變數j記錄現在的位置。函式返回零。」
*longjmp(jmp_buf j,int i)可以接著被呼叫。它表示「回到j所記錄的位置,讓它看上去像是從原來的setjmp()函式返回一樣。但是函式返回i,使**知道它實際上是通過longjmp()返回的。「坳口不?
*當使用longjmp()時,j的內容被銷毀。
*goto語句不能跳出c語言當前的函式(這也是「longjmp」取名的由來,它可以跳的很遠,甚至可以跳到其他檔案的函式中)。
*用longjmp只能跳回到曾經到過的地方。在setjmp的地方仍留有乙個過程活動記錄。從這個角度講,longjmp更像是「從何處阿里(come from)「而不是」往**去(go to)」。longjmp接受乙個額外的整型引數並返回它的值,這可以知道是由longjmp轉移到這裡的還是從上條語句執行後自然而然來的這裡的。
下面的**顯示了setjmp()和longjmp()一例。
#include
#include
jmp_buf buf;
banana()
int main()
else }
輸出結果如下:
first time throught
in banana()
back in main
需要注意的地方是:保證區域性變數在longjmp過程中一直保持它的值的唯一可靠方法是把它宣告為volatile(這使用於那些值在setjmp執行和longjmp返回之間會改變的變數)
另外乙個例子:
setjmp和longjmp函式使用示例:
#include
#include
static jmp_buf buf;
int main()
b = 5;
longjmp(buf, 1);
return 0; }
setjmp執行時返回0,執行b等於5,呼叫longjmp,跳轉到setjmp呼叫,setjmp返回1,列印b=5。
setjmp/longjmp最大的用途是錯誤恢復。只要還沒有從函式中返回,一旦發現乙個不可恢復的錯誤,可以把控制轉移到主輸入迴圈,並從那裡重新開始。有些人使用setjmp/longjmp從一串無數的函式呼叫中立即返回。還有些人用它們防範潛在的危險**。
setjmp/longjmp在c++中演變為更普通的異常處理機制"catch"和"throw"
傳說中的MTU
通訊術語 最大傳輸單元 maximum transmission unit,mtu 是指一種通訊協議的某一層上面所能通過的最大資料報大小 以位元組為單位 最大傳輸單元這個引數通常與通訊介面有關 網路介面卡 串列埠等 網際網路協議允許ip分片,這樣就可以將資料報分成足夠小的片段以通過那些最大傳輸單元小...
傳說中的truncate html
學習用rails做blog的時候要用到rails的truncate功能。h truncate post.content,100,問題來了,將html截斷後出現不完整的tag,導致後續的文章排版都錯亂了。本來考慮是不是自己寫乙個,正在思考思路,結果祭起google,好嗎,已經有牛人寫了 簡單記錄一下 ...
傳說中的分頁6
set quoted identifier off goset ansi nulls on go 名稱 分頁儲存過程 使用示例 exec sp pageindex from stusources 2,10 注意 目前還沒有對輸入的引數進行嚴格的驗證 預設為輸入都是合法有效的 alter proc s...