繁体   English   中英

如何在C ++中的退出时运行函数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM