int setjmp(jmp_buf env):保存當前堆疊上下文(暫存器、堆疊指標、程式計數器)至 env,首次呼叫返回 0。void longjmp(jmp_buf env, int val):恢復 env 保存的上下文,使程式從對應的 setjmp 處繼續執行,且 setjmp 返回 val(非 0)。關鍵限制:longjmp 必須在 setjmp 呼叫後、且 setjmp 所在函數尚未返回(堆疊幀未銷毀)時使用,否則行為未定義。
void main() {
jmp_buf mark;
int jmpret = setjmp(mark);
if (jmpret == 0) {
// 正常執行流
if (error1) longjmp(mark, 1);
if (error2) longjmp(mark, 2);
} else {
// 統一錯誤處理
switch (jmpret) {
case 1: handle_error1(); break;
case 2: handle_error2(); break;
}
}
}
此模式類似 goto 但結構更清晰,適用於單函數多錯誤點統一處理。
jmp_buf mark;
void func1() { if (err) longjmp(mark, 1); }
void func2() { if (err) longjmp(mark, 2); }
void func3() { if (err) longjmp(mark, 3); }
void main() {
int jmpret = setjmp(mark);
if (jmpret == 0) {
func1(); func2(); func3(); // 任一函數出錯直接跳回 main
} else {
// 處理來自任意深度的錯誤
}
}
這實現了類似 C++ 異常的「棧展開」效果:**錯誤可穿透多層函數調用直接到達處理點**,無需層層傳遞錯誤碼。這是 C 語言中實現結構化異常處理的核心手段。
setjmp 後 longjmp。若反序呼叫,程式流不可預測,極易崩潰。setjmp 所在函數返回後,其堆疊幀失效,jmp_buf 失效。全域/靜態 jmp_buf 同理,若對應函數已返回則不可用。free 記憶體)。**必須在 longjmp 目標點手動清理所有已獲取資源**,或設計資源獲取即初始化(RAII 風格)的封裝層。setjmp/longjmp 是 C 語言實現非本地跳轉、模擬異常處理的強大機制,但屬於「手動檔」操作:靈活卻危險。現代 C 專案建議:
errno。cexcept)或升級至 C++。