天天看點

exit、_exit、函數與return的不同

說明:隻供學習交流,裝載請注明出處

正常中止一個程式,可以使用從main函數中傳回、調用exit函數或_exit函數的方法。從main函數中傳回這一方法,常用于獲得程式傳回值這一場合。這時,除了需要定義main函數的類型外,在程式中還需要使用return語句。使用這一方法退出程式隻能用于主函數中,用在子程式中隻能傳回上一級調用程式。

exit函數和_exit函數可以用在子程式中。程式在執行到這兩個函數處,會自動結束并跳回到作業系統中。當然,也可以将這兩個函數用在main函數中。與使用return相比,exit和_exit是不考慮傳回類型的,也就是說,main的類型可以是void或任意類型。

一個簡單的例子:

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

void Exit_Test(void)
{
        printf("Hello linux!\n");
        exit(0);
}

int main(void)
{
        Exit_Test();

        printf("Hello word!\n");

        return (0);
}

輸出結果:
[[email protected] test]# ./exit 
Hello linux!

           

說明:程式并沒有輸出“helloword!”,因為程式運作到exit出了直接退出并跳到作業系統中。

exit函數:

exit函數的定義資訊如下表:

頭檔案 #include <stdlib.h>
函數原型 void exit(int status)
傳回值 成功 失敗 是否設定errno
—— —— ——

說明:調用exit函數結束程序,并将(status & 0377)獲得的結果傳回給父程序。使用exit函數結束程序時,會首先執行使用atexit函數注冊的函數,然後調用on_exit函數中清理動作。函數執行順序與注冊的順序相反。

參數status為退出程序時的狀态,父程序将獲得該狀态值。C語言标準指定了EXIT_SUCCESS和EXIT_FAILURE作為程式正常結束和異常中止的兩個宏。

為了說明使用exit函數退出程式是會執行的相關的動作,這裡給出一個簡單的執行個體。程式用atexit注冊了一個程序退出時的處理函數,該處理函數隻是顯示一段文字資訊。main函數退出時将調用exit函數,這樣程序就會在退出時自動調用atexit注冊的處理函數。

atexit函數定義如下:

int atexit(void (*function) (void));

atexit在成功注冊回調函數後會傳回0值,否則傳回傳回非0值。

代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void do_at_exit(void)
{
        printf("You can see the output when the program terminates\n");
}

int main(void)
{
        int flag;

        flag = atexit(do_at_exit);

        if ( flag != 0 )
        {
                printf("Cannot set exit function!\n");
                return (EXIT_FAILURE);
        }

        exit(EXIT_SUCCESS);
}
運作結果:
[[email protected] test]# ./atexit 
You can see the output when the program terminates
[[email protected] test]# 

           

說明:在main中調用return函數同樣會在程式退出時執行使用atexit注冊的處理動作。是以,使用return代替exit函數同樣會獲得相同的結果。

_exit函數:

與exit函數類似,_exit函數同樣可以用于退出程序,這兩個函數存在一定的差別。在介紹vfork函數的使用時,提到了子程序的退出隻能使用_exit函數,具體原因并沒有闡述。這裡首先介紹其定義,然後通過執行個體來說明它們之間的差別。

_exit函數的定義如下表:

頭檔案 #include <unistd.h>
函數原型 void _exit(int status)
傳回值 成功 失敗 是否設定errno
—— —— ——

說明:_exit函數将立即結束調用它的程序,與程序相關的任何打開的檔案描述符都将關閉,程序的子程序都将變為init程序(程序号為1)的子程序。

參數status為退出程序時的狀态,父程序将獲得該狀态值。C語言标準指定了EXIT_SUCCESS和EXIT_FAILURE作為程式正常結束和異常中止的兩個宏。

我們同樣使用上面的那個執行個體,隻是把exit該為_exit退出,其他的都是一樣,之是以使用同一個例子是為了說明_exit退出程式時,不會執行atexit注冊的處理函數。

執行個體:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void do_at_exit(void)
{
        printf("You can see the output when the program terminates\n");
}

int main(void)
{
        int flag;

        flag = atexit(do_at_exit);

        if ( flag != 0 )
        {
                printf("Cannot set exit function!\n");
                return (EXIT_FAILURE);
        }

        _exit(EXIT_SUCCESS);
}
運作結果:
[[email protected] test]# ./atexit 
[[email protected] test]#

           

exit函數與_exit函數的差別:

(1):exit函數隻是在ANSI C中說明的,而_exit函數是在POSIX标準中說明的。

(2):exit函數将終止調用程序,在退出程式之前所有檔案關閉,标準輸入輸出的緩沖區被清空,并執行在atexit注冊的回調函數;_exit終止調用程序,但不關閉檔案,不清除标準輸入輸出緩存區,也不調用在atexit注冊的回調函數。

說明:在系統調用fork建立的子程序中,一般情況下盡量不要使用exit函數退出子程序。因為exit會導緻标準輸入輸出的緩沖區被清空。對應C++程式,問題可能會更嚴重。exit函數有可能導緻靜态目标檔案中的析構函數被錯誤執行。使用exit函數時,必須保證exit在進入main函數後隻會被調用一次。而使用vfork時,由于父子程序共享虛拟記憶體空間,子程序使用exit将會影響父程序的狀态。