標籤:
1. exit函數
C,C++函數exit用來終止當前程式, 函數定義如下:
- void exit (int status);
官方說明如下:
Terminates the process normally, performing the regular cleanup for terminating programs.
Normal program termination performs the following (in the same order):
- Objects associated with the current thread with thread storage duration are destroyed (C++11 only).
- Objects with static storage duration are destroyed (C++) and functions registered withatexit are called.
- All C streams (open with functions in <cstudio>) are closed (and flushed, if buffered), and all files created with tmpfile are removed.
- Control is returned to the host environment.
第三第四點比較容易理解就不展開討論
第一點:
這裡的thread storage指的是線程局部儲存, 線上程範圍有效, c++11定義thread storage如下:
[html] view plaincopy
- thread_local Object obj; //Object為C++類
- thread_local int value = 1;
第二點:static storage指的是全域或者函數中static方式定義的變數, 該部分變數會儲存到靜態儲存區(區別於heap和stack), 比如:
[html] view plaincopy
- Object gObj;
-
- void fun(){
-
- static Object sObj;
-
- }
atexit設定的函數在exit過程中會被調用, atexit函數定義如下:
[html] view plaincopy
- int atexit (void (*func)(void));
atexit例子如下:
[cpp] view plaincopy
- /* atexit example */
- #include <stdio.h> /* puts */
- #include <stdlib.h> /* atexit */
-
- void fnExit1 (void)
- {
- puts ("Exit function 1.");
- }
-
- void fnExit2 (void)
- {
- puts ("Exit function 2.");
- }
-
- int main ()
- {
- atexit (fnExit1);
- atexit (fnExit2);
- puts ("Main function.");
- exit(0);
- }
輸出為:
[html] view plaincopy
- Main function.
- Exit function 2.
- Exit function 1.
對C++ object銷毀順序, 可以看以下例子:
[cpp] view plaincopy
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <thread>
- #include <string>
- #include <iostream>
-
- class MyObject
- {
- public:
- std::string str;
- public:
- MyObject(std::string str){
- this->str = str;
- }
-
- ~MyObject(){
- printf("%s -- %s\n", __FUNCTION__, str.c_str());
- }
- };
-
-
- void thread_fun(int n)
- {
- thread_local MyObject threadObj("thread_local subthread obj");
- //do something
- sleep(2);
- }
-
- void exit_fun(){
- MyObject threadObj("atexit obj");
- //do something
- sleep(1);
- }
-
- MyObject obj("global obj");
- int main(int argc, const char * argv[])
- {
- thread_local MyObject threadObj("thread_local mainthread obj");
- static MyObject staticObj("fun static obj");
- std::thread t(thread_fun, 1);
- atexit(exit_fun);
-
- sleep(2);
- exit(0);
- }
輸出:
[cpp] view plaincopy
- ~MyObject -- thread_local subthread obj
- ~MyObject -- thread_local mainthread obj
- ~MyObject -- atexit obj
- ~MyObject -- fun static obj
- ~MyObject -- global obj
- Program ended with exit code: 0
從上面可以看出, 對於第二點是先調用atexit, 再清理static storage
2. exit vs abort
void abort (void);
abort函數實際上是發送SIGABRT signal, 如果不處理則直接終止程式,此時並不會做cleanup操作,相當於直接終止程式。
3. IOS exit函數
雙擊Home 手動kill掉程式, 會調用exit函數關閉程式, __cxa_finalize函數會執行上面講到清理工作。
如果重載了AppDelegate applicationWillTerminate函數,則在執行exit之前會調用該函數,終止前提供開發人員程式處理機會。
如果程式已經退到後台並處於suspend狀態, 這時手動kill並不會按照上面方式調用exit, 而是發送SIGKILL signal, 直接終止程式。
4. exit和多線程當exit被調用時, 如果其它線程正在執行並且訪問了 global或者staic c++ object對象時, 則可能由於這些對象已被銷毀而出現無法預期的記憶體錯誤,比如:SIGBUS,SIGSEGV。 如需避免該問題可以有以下一些處理方案:
1). 把對象從static storage移動heap上, 避免exit過程銷毀對象而出現非預期結果比如:
[html] view plaincopy
- MyObject gObj("global obj");
- // ------>
- MyObject* pObj = new MyObject("global obj ptr");
2). 通過atexit註冊回調, 或者applicationWillTerminate(iOS) 中結束子線程避免引用可能銷毀的對象。
5. iOS上終止程式
1). 主動調用exit或使用者終止(程式未進入suspend狀態,
applicationDidEnterBackground未回調
)
在iOS上可以直接調用exit(0)終止程式,也會按照上面說到的cleanup清理c++ object. (註:iOS 7.0模擬器未做清理,iPhone和7.1模擬器都ok, 估計是模擬器bug)
2). 如果程式已經進入suspend狀態
applicationDidEnterBackground已經回調,則系統會直接發送SIGKILL強製程序直接結束
iOS終止函數exit