[英]How do you run a function on exit in C++
我有一個要在程序退出時運行的函數:
void foo() {
std::cout<< "Exiting" << std::endl;
}
我如何注冊它以便在程序存在時運行,無論何時,為什么退出(由於信號,exit()調用等)?
您可以在cstdlib
標頭中使用恰當命名的std::atexit
函數:
#include <cstdlib>
void exiting() {
std::cout << "Exiting";
}
int main() {
std::atexit(exiting);
}
系統將維護一堆在atexit
注冊的函數,並在調用exit
函數或程序從main
返回時以與注冊相反的順序調用它們。 您可以這樣注冊至少32個功能。
我以Linux用戶的身份回答,但所有這些都應適用於Windows。
我也有類似的問題,所以希望我可以總結一下以前的答案,並加兩分錢。
信號和abort()
:可以在退出之前“攔截” ^C
和^Z
來調用您的函數,大概是通過exit()進行。 沒有按鍵擊的信號SIGQUIT
AKA ^\\
和SIGKILL
。 這是使用csignal
標頭和C ++ lambda的示例。
#include <iostream>
#include <csignal>
#include <cstdlib>
using namespace std;
int main()
{
//signal requires lam take an int parameter
//this parameter is equal to the signals value
auto lam =
[] (int i) { cout << "aborting" << endl; exit(0); };
//^C
signal(SIGINT, lam);
//abort()
signal(SIGABRT, lam);
//sent by "kill" command
signal(SIGTERM, lam);
//^Z
signal(SIGTSTP, lam);
while(1)
{
}
return 0;
}
退出:由於我在上面的示例中使用了exit()
,因此在此必須小心。 如果正在運行的函數是僅需要運行一次的清理函數, has_run
可以使用靜態變量has_run
。 或者在上面的示例中, raise()
一個您無法攔截的信號。 但是那些往往帶有核心轉儲,感覺很臟。 您的選擇,在這里。 一個例子如下
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
//called with no parameters
auto lam = [] () { cout << "at exit"; };
atexit(lam);
return 0;
}
請注意,c ++ 11添加了一個quick_exit
,它具有一個伴隨的at_quick_exit
,其作用與上述相同。 但是使用quick_exit
不會執行清理任務。 相反,使用exit
對象時,將調用析構函數,並關閉C流,而不會清除自動存儲變量。
您可以將其放在具有全局實例的類的析構函數中。
class SomeGlobalStuff {
~SomeGlobalStuff() {
foo();
}
static SomeGlobalStuff instance;
};
// putting this in a single compilation unit.
SomeGlobalStuff SomeGlobalStuff::instance instance;
但是,與任何其他方法一樣,您必須記住,如果不能保證任何數據仍然存在,就不能使用任何數據。 全局對象的取消分配以任意順序完成,因此,基本上,您不能在foo()函數中使用std :: cout。 就此而言,atexit()更糟,因為它是在銷毀全局對象之前還是之后執行取決於編譯器和編譯器選項。
而且無論如何,您仍然必須正確處理信號。 您必須選擇要處理和不處理的信號(您很可能不想處理SIGSEGV)。 您無法逃避信號處理。 請記住,信號可能會隨時中斷程序(除非被屏蔽),因此在更新過程中,數據結構可能處於任意狀態。
在進程退出后重新獲得控制權的唯一方法(在Unix和類似Unix的操作系統中)是wait(2)
。 如果沒有電源故障,內核崩潰或強制重啟,這應該可以工作:
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
int AtExit() {
pid_t pid = fork();
if(pid < 0) return pid;
if(pid == 0) return pid;
pid = waitpid(pid, 0, 0);
return pid;
}
int main () {
if(AtExit()) {
std::cout << "Exiting\n";
return 0;
}
std::cout << 7 << "\n";
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.