日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C异常处理实现: setjmp和longjmp

發布時間:2025/7/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C异常处理实现: setjmp和longjmp 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

此文為internet上選摘,過后我會用自己的理解補充此文。

------------

將對setjmp與longjmp的具體使用方法和適用的場合,進行一個非常全面的闡述。

另外請特別注意,setjmp函數與longjmp函數總是組合起來使用,它們是緊密相關的一對操作,只有將它們結合起來使用,才能達到程序控制流有效轉移的目的,才能按照程序員的預先設計的意圖,去實現對程序中可能出現的異常進行集中處理。

與goto語句的作用類似,它能實現本地的跳轉

這種情況容易理解,不過還是列舉出一個示例程序吧!如下:

void main( void )
{
int jmpret;

jmpret = setjmp( mark );
if( jmpret == 0 )
{
// 其它代碼的執行
// 判斷程序遠行中,是否出現錯誤,如果有錯誤,則跳轉!
if(1) longjmp(mark, 1);

// 其它代碼的執行
// 判斷程序遠行中,是否出現錯誤,如果有錯誤,則跳轉!
if(2) longjmp(mark, 2);

// 其它代碼的執行
// 判斷程序遠行中,是否出現錯誤,如果有錯誤,則跳轉!
if(-1) longjmp(mark, -1);

// 其它代碼的執行
}
else
{
// 錯誤處理模塊
switch (jmpret)
{
case 1:
printf( "Error 1"n");
break;
case 2:
printf( "Error 2"n");
break;
case 3:
printf( "Error 3"n");
break;
default :
printf( "Unknown Error");
break;
}
exit(0);
}

return;
}

   上面的例程非常地簡單,其中程序中使用到了異常處理的機制,這使得程序的代碼非常緊湊、清晰,易于理解。在程序運行過程中,當異常情況出現后,控制流是 進行了一個本地跳轉(進入到異常處理的代碼模塊,是在同一個函數的內部),這種情況其實也可以用goto語句來予以很好的實現,但是,顯然setjmp與 longjmp的方式,更為嚴謹一些,也更為友善。程序的執行流如圖17-1所示。



setjmp與longjmp相結合,實現程序的非本地的跳轉

呵呵!這就是goto語句所不能實現的。也正因為如此,所以才說在C語言中,setjmp與longjmp相結合的方式,它提供了真正意義上的異常處 理機制。其實上一篇文章中的那個例程,已經演示了longjmp函數的非本地跳轉的場景。這里為了更清晰演示本地跳轉與非本地跳轉,這兩者之間的區別,我 們在上面剛才的那個例程基礎上,進行很小的一點改動,代碼如下:

void Func1()
{
// 其它代碼的執行
// 判斷程序遠行中,是否出現錯誤,如果有錯誤,則跳轉!
if(1) longjmp(mark, 1);
}

void Func2()
{
// 其它代碼的執行
// 判斷程序遠行中,是否出現錯誤,如果有錯誤,則跳轉!
if(2) longjmp(mark, 2);
}

void Func3()
{
// 其它代碼的執行
// 判斷程序遠行中,是否出現錯誤,如果有錯誤,則跳轉!
if(-1) longjmp(mark, -1);
}

void main( void )
{
int jmpret;

jmpret = setjmp( mark );
if( jmpret == 0 )
{
// 其它代碼的執行

// 下面的這些函數執行過程中,有可能出現異常
Func1();

Func2();

Func3();

// 其它代碼的執行
}
else
{
// 錯誤處理模塊
switch (jmpret)
{
case 1:
printf( "Error 1"n");
break;
case 2:
printf( "Error 2"n");
break;
case 3:
printf( "Error 3"n");
break;
default :
printf( "Unknown Error");
break;
}
exit(0);
}

return;
}

回顧一下,這與C++中提供的異常處理模型是不是很相近。異常的傳遞是可以跨越一個或多個函數。這的確為C程序員提供了一種較完善的異常處理編程的機制或手段。

setjmp和longjmp使用時,需要特別注意的事情

1、setjmp與longjmp結合使用時,它們必須有嚴格的先后執行順序,也即先調用setjmp函數,之后再調用longjmp函數,以恢復到 先前被保存的“程序執行點”。否則,如果在setjmp調用之前,執行longjmp函數,將導致程序的執行流變的不可預測,很容易導致程序崩潰而退出。 請看示例程序,代碼如下:

class Test
{
public:
Test()
~Test()
}obj;

//注意,上面聲明了一個全局變量obj

void main( void )
{
int jmpret;

// 注意,這里將會導致程序崩潰,無條件退出
Func1();
while(1);

jmpret = setjmp( mark );
if( jmpret == 0 )
{
// 其它代碼的執行

// 下面的這些函數執行過程中,有可能出現異常
Func1();

Func2();

Func3();

// 其它代碼的執行
}
else
{
// 錯誤處理模塊
switch (jmpret)
{
case 1:
printf( "Error 1"n");
break;
case 2:
printf( "Error 2"n");
break;
case 3:
printf( "Error 3"n");
break;
default :
printf( "Unknown Error");
break;
}
exit(0);
}

return;
}

  上面的程序運行結果,如下:
構造對象
Press any key to continue

   的確,上面程序崩潰了,由于在Func1()函數內,調用了longjmp,但此時程序還沒有調用setjmp來保存一個程序執行點。因此,程序的執行 流變的不可預測。這樣導致的程序后果是非常嚴重的,例如說,上面的程序中,有一個對象被構造了,但程序崩潰退出時,它的析構函數并沒有被系統來調用,得以 清除一些必要的資源。所以這樣的程序是非常危險的。(另外請注意,上面的程序是一個C++程序,所以大家演示并測試這個例程時,把源文件的擴展名改為 xxx.cpp)。

  2、除了要求先調用setjmp函數,之后再調用longjmp函數(也即longjmp必須有對應的setjmp函數)之外。另外,還有一個很重要的規則,那就是longjmp的調用是有一定域范圍要求的。這未免太抽象了,還是先看一個示例,如下:

int Sub_Func()
{
int jmpret, be_modify;

be_modify = 0;

jmpret = setjmp( mark );
if( jmpret == 0 )
{
// 其它代碼的執行
}
else
{
// 錯誤處理模塊
switch (jmpret)
{
case 1:
printf( "Error 1"n");
break;
case 2:
printf( "Error 2"n");
break;
case 3:
printf( "Error 3"n");
break;
default :
printf( "Unknown Error");
break;
}

//注意這一語句,程序有條件地退出
if (be_modify==0) exit(0);
}

return jmpret;
}

void main( void )
{
Sub_Func();

// 注意,雖然longjmp的調用是在setjmp之后,但是它超出了setjmp的作用范圍。
longjmp(mark, 1);
}

  如果你運行或調試(單步跟蹤)一下上面程序,發現它真是挺神奇的,居然longjmp執行時,程序還能夠返回到setjmp的執行點,程序正常退出。但是這就說明了上面的這個例程的沒有問題嗎?我們對這個程序小改一下,如下:

int Sub_Func()
{
// 注意,這里改動了一點
int be_modify, jmpret;

be_modify = 0;

jmpret = setjmp( mark );
if( jmpret == 0 )
{
// 其它代碼的執行
}
else
{
// 錯誤處理模塊
switch (jmpret)
{
case 1:
printf( "Error 1"n");
break;
case 2:
printf( "Error 2"n");
break;
case 3:
printf( "Error 3"n");
break;
default :
printf( "Unknown Error");
break;
}

//注意這一語句,程序有條件地退出
if (be_modify==0) exit(0);
}

return jmpret;
}

void main( void )
{
Sub_Func();

// 注意,雖然longjmp的調用是在setjmp之后,但是它超出了setjmp的作用范圍。
longjmp(mark, 1);
}

   運行或調試(單步跟蹤)上面的程序,發現它崩潰了,為什么?這就是因為,“在調用setjmp的函數返回之前,調用longjmp,否則結果不可預料” (這在上一篇文章中已經提到過,MSDN中做了特別的說明)。為什么這樣做會導致不可預料?其實仔細想想,原因也很簡單,那就是因為,當setjmp函數 調用時,它保存的程序執行點環境,只應該在當前的函數作用域以內(或以后)才會有效。如果函數返回到了上層(或更上層)的函數環境中,那么setjmp保 存的程序的環境也將會無效,因為堆棧中的數據此時將可能發生覆蓋,所以當然會導致不可預料的執行后果。

   3、不要假象寄存器類型的變量將總會保持不變。在調用longjmp之后,通過setjmp所返回的控制流中,例程中寄存器類型的變量將不會被恢復。 (MSDN中做了特別的說明,上一篇文章中,這也已經提到過)。寄存器類型的變量,是指為了提高程序的運行效率,變量不被保存在內存中,而是直接被保存在 寄存器中。寄存器類型的變量一般都是臨時變量,在C語言中,通過register定義,或直接嵌入匯編代碼的程序。這種類型的變量一般很少采用,所以在使 用setjmp和longjmp時,基本上不用考慮到這一點。

4、MSDN中還做了特別的說明,“在C+ +程序中,小心對setjmp和longjmp的使用,因為setjmp和longjmp并不能很好地支持C++中面向對象的語義。因此在C++程序中, 使用C++提供的異常處理機制將會更加安全。”雖然說C++能非常好的兼容C,但是這并非是100%的完全兼容。例如,這里就是一個很好的例子,在C++ 程序中,它不能很好地與setjmp和longjmp和平共處。在后面的一些文章中,有關專門討論C++如何兼容支持C語言中的異常處理機制時,會做詳細 深入的研究,這里暫且跳過

轉載于:https://www.cnblogs.com/chio/archive/2008/10/06/1305109.html

總結

以上是生活随笔為你收集整理的C异常处理实现: setjmp和longjmp的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产偷拍一区二区三区 | 久久精品一日日躁夜夜躁 | 国产精品一区免费观看 | 亚洲少妇30p | 97久久久久久 | www.av777 | 99热只有| 午夜男人天堂 | 亚洲综合在线一区 | 91精品久久久久久久久 | 99热国产 | 野花国产精品入口 | 中国字幕av | 中文字幕7| 国产www在线 | 亚洲成成品网站 | 波多野结衣免费视频观看 | 女人十八岁毛片 | 在线污视频| 秋霞黄色网 | 免费久久久 | 欧美久久久久 | 天天干天天爱天天射 | 国产一级一级片 | 性生活视频网站 | 蜜桃成人无码区免费视频网站 | 99日韩 | 麻豆网站在线播放 | 免费在线不卡视频 | 很污很黄的网站 | 色香蕉av| 国产麻豆免费视频 | 国产精品无码av在线播放 | 久久91久久 | 色com| 日本少妇bbb | 91色交视频 | 美女黄色小视频 | 美女网站在线看 | 九九在线免费视频 | 日本一区电影 | 丰满人妻老熟妇伦人精品 | 免费av在线网| 来吧亚洲综合网 | 国产又粗又猛又爽又黄的视频一 | 久久婷婷精品 | www九九热 | 久久精品国产精品亚洲 | 亚洲精品鲁一鲁一区二区三区 | 亚洲毛片在线免费观看 | 一二区免费视频 | 丰满少妇久久久久久久 | 欧美高清二区 | 性xxx欧美 | 美女色诱男人激情视频 | 国产精品无码网站 | 快播久久 | 神马午夜麻豆 | 精品嫩模一区二区三区 | japanese中文字幕 | 9人人澡人人爽人人精品 | 伊人小视频| 西西人体做爰大胆gogo | 午夜视频在线观看视频 | 亚洲性少妇 | 日本大奶视频 | 先锋资源网av | 久久久国产成人一区二区三区 | 国产精品久久99 | 日韩欧美麻豆 | 精品看片| 狠狠操人人干 | 又黄又骚的视频 | 国产亚洲精品久久久久久 | 国产三级视频网站 | 97香蕉| 亚洲日本中文字幕 | 久久久久久久一区二区 | 爱操在线 | 久久久久亚洲av片无码v | 青青操国产视频 | 免费a在线 | 1000部拍拍拍18勿入免费视频 | 日本一区二区视频在线播放 | av乱码 | 成人午夜激情网 | 黄色网久久 | 日韩av无码一区二区三区不卡 | 国产又黄又粗又猛又爽视频 | 日本成人黄色 | 波多野在线播放 | 国产不卡在线观看视频 | 阿娇全套94张未删图久久 | 性喷潮久久久久久久久 | 粉嫩一区二区三区 | 六月婷婷av| 国产精品无码专区av在线播放 | 国产午夜一区 | 欧美性猛交xxxxx水多 |