setjmp和longjmp函數使用詳解

來源:互聯網
上載者:User

非局部跳躍陳述式---setjmp和longjmp函數。非局部指的是,這不是由普通C語言goto,語句在一個函數內實施的跳轉,而是在棧上跳過若干調用幀,返回到當前函數調用路徑上的某一個函數中。
#include <setjmp.h>
Int setjmp(jmp_buf  env);
   傳回值:若直接調用則返回0,若從longjmp調用返回則返回非0值
Void longjmp(jmp_buf env,int val);
    在希望返回到的位置調用setjmp,此位置在main函數中,因為直接調用該函數,所以其傳回值為0.setjmp參數evn的類型是一個特殊的類型jmp_buf,這一資料類型是某種形式的數組,其中存放在調用longjmp時能用來恢複棧狀態的所有資訊。因為需要在另一個函數中引用env變數,所以規範的處理方式是將env變數定義為全域變數。
   當檢查到一個錯誤時,則以兩個參數調用longjmp函數,第一個就是在調用setjmp時所用的env,第二個參數是具有非0值的val,它將成為從setjmp處返回的值。使用第二個參數的原因是對於一個setjmp可以有多個longjmp。
    下面我們可以看一個簡單的例子:

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>

void fun1(void);
void fun2(void);
 jmp_buf jmpbuffer;
void main(void)
{
    int i = 0;
    int j = 0;
    i = setjmp(jmpbuffer);
    if(i==0)
    {
        printf("first run/n");
        fun1();
        fun2();
    }
   else
   {
     switch(i)
     {
       
     case 1:
       printf("In fun1 /n");
     break;
   case 2:
     printf("In fun2/n");
     break;
   default:
     printf("unkown error/n");
     break;
     }
          exit(0);
   }
    return 1;

void fun1(void)
{
    char *s = "hello";
    char *s1 = "Hello";
    if(strcmp(s,s1)!=0)
    longjmp(jmpbuffer,1);
}

void fun2(void)
{
    char *s = "world";
    if(strcmp(s,"World")!=0)
    longjmp(jmpbuffer,2);
}

這個函數的運行結果是:

root@root:~/program/test_program$ ./jmp_test
first run
In fun1

   在使用longjmp跳轉到setjmp中時,程式主動的退出了!相當於拋出一個異常退出!其實這兩個函數可以類比C++中的異常函數:
使用setjmp和longjmp要注意以下幾點:
  1、setjmp與longjmp結合使用時,它們必須有嚴格的先後執行順序,也即先調用setjmp函數,之後再調用longjmp函數,以恢複到先前被儲存的“程式執行點”。否則,如果在setjmp調用之前,執行longjmp函數,將導致程式的執行流變的不可預測,很容易導致程式崩潰而退出
 2、不要假設寄存器類型的變數將總會保持不變。在調用longjmp之後,通過setjmp所返回的控制流程中,程式中寄存器類型的變數將不會被恢複。寄存器類型的變數,是指為了提高程式的運行效率,變數不被儲存在記憶體中,而是直接被儲存在寄存器中。寄存器類型的變數一般都是臨時變數,在C語言中,通過register定義,或直接嵌入彙編代碼的程式。這種類型的變數。
     longjmp必須在setjmp調用之後,而且longjmp必須在setjmp的範圍之內。具體來說,在一個函數中使用setjmp來初始化一個全域標號,然後只要該函數未曾返回,那麼在其它任何地方都可以通過longjmp調用來跳轉到 setjmp的下一條語句執行。實際上setjmp函數將發生調用處的局部環境儲存在了一個jmp_buf的結構當中,只要主調函數中對應的記憶體未曾釋放 (函數返回時局部記憶體就失效了),那麼在調用longjmp的時候就可以根據已儲存的jmp_buf參數恢複到setjmp的地方執行。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.