【VS开发】Return与Exit的区别
1. exit用于結束正在運行的整個程序,它將參數返回給OS,把控制權交給操作系統;而return 是退出當前函數,返回函數值,把控制權交給調用函數。
2. exit是系統調用級別,它表示一個進程的結束;而return 是語言級別的,它表示調用堆棧的返回。
3. 在main函數結束時,會隱式地調用exit函數,所以一般程序執行到main()結尾時,則結束主進程。exit將刪除進程使用的內存空間,同時把錯誤信息返回給父進程。
4. void exit(int status); 一般status為0,表示正常退出,非0表示非正常退出。
1、exit函數和return函數的主要區別是:
1)exit用于在程序運行的過程中隨時結束程序,其參數是返回給OS的。也可以這么講:exit函數是退出應用程序,并將應用程序的一個狀態返回給OS,這個狀態標識了應用程序的一些運行信息。
main函數結束時也會隱式地調用exit函數,exit函數運行時首先會執行由atexit()函數登記的函數,然后會做一些自身的清理工作,同時刷新所有輸出流、關閉所有打開的流并且關閉通過標準I/O函數tmpfile()創建的臨時文件。
exit是系統調用級別的,它表示了一個進程的結束,它將刪除進程使用的內存空間,同時把錯誤信息返回父進程。通常情況:exit(0)表示程序正常, exit(1)和exit(-1)表示程序異常退出,exit(2)表示系統找不到指定的文件。在整個程序中,只要調用exit就結束。
?
2)return是語言級別的,它表示了調用堆棧的返回;return是返回函數值并退出函數,通常0為正常退出,非0為非正常退出,請注意,如果是在主函數main, 自然也就結束當前進程了(也就是說,在main()里面,你可以用return n,也能夠直接用exit(n)來做),如果不是在main函數中,那就是退回上一層調用。在多個進程時,如果有時要檢測上個進程是否正常退出,就要用到上個進程的返回值。
?
2、進程環境與進程控制
exit(int n)其實就是直接退出程序,因為默認的標準程序入口為 int main(int argc, char** argv),返回值是int型的。一般在shell下面,運行一個程序,然后使用命令echo $?就能得到該程序的返回值,也就是退出值。
理論上exit可以返回小于256的任何整數,返回的不同數值主要是給調用者作不同處理的。
對于單獨的進程exit的返回值是返回給操作系統的,但如果是多進程,則是返回給父進程的。父進程里面調用waitpid()等函數得到子進程退出的狀態,以便作不同處理。根據相應的返回值來讓調用者作出相應的處理。
總的說來,exit()就是當前進程把其控制權返回給調用該子程序的主程序, 括號里的是返回值,告訴調用程序該程序的運行狀態。
?
1)進程的開始:
C程序是從main函數開始執行, 原型如下: int main(int argc, char *argv[]); 通常main的返回值是int型, 正確返回0。?
2)進程終止:?
C程序的終止分為兩種: 正常終止和異常終止。正常終止分為: return, exit, _exit, _Exit, pthreade_exit。異常中指分為: abort, SIGNAL, 線程響應取消。
主要說一下正常終止的前4種, 即exit系列函數.
#include <stdlib.h>??
void exit(int status);
void _Exit(int status);
?
#include <unistd.h>??
void _exit(int status);
以上3個函數的區別是: exit()(或return 0)會調用終止處理程序和用戶空間的標準I/O清理程序(如fclose), _exit和_Exit不調用而直接由內核接管進行清理。因此, 在main函數中exit(0)等價于return 0.
?
3)atexit終止處理程序:
ISO C規定, 一個進程最多可登記32個終止處理函數, 這些函數由exit按登記相反的順序自動調用。如果同一函數登記多次, 也會被調用多次。
?
原型如下:?
#include <stdlib.h>
int atexit(void (*func)(void));
?
其中參數是一個函數指針, 指向終止處理函數, 該函數無參無返回值。atexit函數本身成功調用后返回0。
?
以下面的程序為例:
?
#include <stdlib.h>?
static void myexit1()
{
???? printf("first exit handler\n");
}?
static void myexit2()
{
???? printf("second exit handler\n");
}?
int main()
{
???? atexit(my_exit2);
?? ??atexit(my_exit1);
atexit(my_exit1);
???? printf("main is done\n");
???? return 0;
}
?
運行結果:
$ ./a.out
main is done
first exit handler
first exit handler
second exit handler
? ? 注意上面的結果,可以發現這些函數由exit按登記相反的順序自動調用(先myexit1后myexit2)。如果同一函數登記多次, 也會被調用多次(如這里的myexit1)。而這些處理函數都是在程序退出的時候利用atexit函數調用了這些處理函數。但是如果用_exit()退出程序,則它不關閉任何文件,不清除任何緩沖器、也不調用任何終止函數!
exit函數在頭文件stdlib.h中。
exit(0):正常運行程序并退出程序;
exit(1):非正常運行導致退出程序;
return():返回函數,若在main主函數中,則會退出函數并返回一值,可以寫為return(0),或return 0。
詳細說:
??1. return返回函數值,是關鍵字;exit是一個函數。
? 2. return是語言級別的,它表示了調用堆棧的返回;而exit是系統調用級別的,它表示了一個進程的結束。
? 3. return是函數的退出(返回);exit是進程的退出。
? 4. return是C語言提供的,exit是操作系統提供的(或者函數庫中給出的)。
? 5. return用于結束一個函數的執行,將函數的執行信息傳出個其他調用函數使用;exit函數是退出應用程序,刪除進程使用的內存空間,并將應用程序的一個狀態返回給OS,這個狀態標識了應用程序的一些運行信息,這個信息和機器和操作系統有關,一般是?0 為正常退出,非0 為非正常退出。
? 6. 非主函數中調用return和exit效果很明顯,但是在main函數中調用return和exit的現象就很模糊,多數情況下現象都是一致的。
?下面是幾個例子:
1.
| #include <unistd.h> #include <stdio.h> #include <stdlib.h> ?? int?main(void) { pid_t pid; int?count=0; ?? pid=vfork(); if(pid==0) { printf("child: count=%d\n",count); printf("child: getpid=%d\n",getpid()); count=1; printf("child: count=%d\n",count); // return 0;//會出現段錯誤 exit(0);?//ok } else { printf("\nfather: pid=%d\n",pid); printf("father: count=%d\n",count); } return(0); } |
?
運行結果
?| [root@localhost part1_linux]# gcc fork2.c? [root@localhost part1_linux]# ./a.out? child: count=0 child: getpid=9911 child: count=1 ?? father: pid=9911 father: count=1 |
運行結果說明:vfrok時父、子進程共享數據段,fork時是進行拷貝。如果,vfork子進程中,使用return返回時,出現段錯誤,結果如下:
?| [root@localhost part1_linux]# gcc fork2.c? [root@localhost part1_linux]# ./a.out? child: count=0 child: getpid=10864 child: count=1 ?? father: pid=10864 father: count=0 段錯誤 |
| #include <stdio.h> #include <sys/types.h> #include <unistd.h> ?? int?main() { ????int?i=0; ????pid_t pid; ????printf("還沒創建子進程\n"); ????i++; ????pid = fork(); ????if(pid==-1) ????{ ???? printf("fork error!\n"); ????} ????else?if(pid==0) ????{ ???? i++; ???? printf("我是子進程,id%d\n",getpid()); ? printf("我的父親是id:%d\n",getppid()); printf("-----i=%d-----\n",i); ????} ????else ????{ ???? i++; ???? printf("我是父進程,id:%d\n",getpid()); ???? printf("-----i=%d-----\n",i); ????} ????exit(0); } |
| #include <stdio.h> #include <sys/types.h> #include <unistd.h> ?? int?main() { int?i=0; pid_t pid; printf("還沒創建子進程\n"); i++; pid = vfork(); if(pid==-1) { printf("fork error!\n"); } else?if(pid==0) { i++; printf("我是子進程,id%d\n",getpid()); printf("我的父親是id:%d\n",getppid()); printf("-----i=%d-----\n",i); } else { i++; printf("我是父進程,id:%d\n",getpid()); printf("-----i=%d-----\n",i); } return(0); |
轉載于:https://www.cnblogs.com/huty/p/8518849.html
總結
以上是生活随笔為你收集整理的【VS开发】Return与Exit的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bs4_2
- 下一篇: JVM原理和性能调优