前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入浅出 C++:与程序终止相关的函数 PART 2 - quick_exit()、_Exit()

深入浅出 C++:与程序终止相关的函数 PART 2 - quick_exit()、_Exit()

作者头像
用户7886150
修改2021-02-14 10:09:40
1.3K0
修改2021-02-14 10:09:40
举报
文章被收录于专栏:bit哲学院

参考链接: C++ at_quick_exit()

quick_exit() 与 at_quick_exit() (C++11新增) 

[[noreturn]] void quick_exit(int status) noexcept; 

quick_exit() 为 C++11 引入的函数,如果程序有特殊理由,想直接结束、但又不希望呼叫到对象的 destructor 时,就能派上用处。 

相对于 exit() 与 atexit(),quick_exit() 亦有 at_quick_exit(),用来注册当 quick_exit() 调用后,还需处理的事情。C++ 标准同样保证 at_quick_exit() 至少能注册 32 个函数,且执行的顺序与注册的顺序相反。 

extern "C" int at_quick_exit (void (*func)(void)) noexcept;

extern "C++" int at_quick_exit (void (*func)(void)) noexcept; 

at_quick_exit 注册的函数,与 at_exit 注册的是隔离的,两不相干,端看程序是以 exit() 结束、还是 quick_exit() 结束。若 main() 函数正常结束,则是调用 exit()、并触发 at_exit() 注册的函数执行。 

#include <iostream>

#include <cstdlib>

#include <thread>

void Print(const std::string&s, int m)

{

  std::cout << s << ", m_ = " << m

            << ", thread_id = " << std::this_thread::get_id() << std::endl;

}

class MyClass

{

public:

  MyClass(int a) : m_(a) { Print("Constructor", m_); }

  ~MyClass()             { Print("Destructor", m_);  }

  void Show()            { Print("Show", m_);        }

private:

  int m_;

};

void ExitFunction1() { std::cout << "ExitFunction1()" << std::endl; }

void ExitFunction2() { std::cout << "ExitFunction2()" << std::endl; }

void ExitFunction3() { std::cout << "ExitFunction3()" << std::endl; }

void ExitFunction4() { std::cout << "ExitFunction4()" << std::endl; }

MyClass c1(1);

thread_local MyClass c2(2);

int main()

{

  std::cout << "Begin of main()" << std::endl;

  static MyClass c3(3);

  MyClass c4(4);

  c2.Show();

  std::atexit(ExitFunction1);

  std::at_quick_exit(ExitFunction2);

  std::at_quick_exit(ExitFunction3);

  std::at_quick_exit(ExitFunction4);

  std::cout << "Call quick_exit()" << std::endl;

  std::quick_exit(EXIT_SUCCESS);

  std::cout << "End of main()" << std::endl;

sora@sora-VirtualBox:~/cpp/c2$ clang++ -std=c++17 -stdlib=libc++ --pedantic-errors -pthread -o quick_exit quick_exit.cpp

sora@sora-VirtualBox:~/cpp/c2$ ./quick_exit 

Constructor, m_ = 1, thread_id = 140176298325824

Begin of main()

Constructor, m_ = 3, thread_id = 140176298325824

Constructor, m_ = 4, thread_id = 140176298325824

Constructor, m_ = 2, thread_id = 140176298325824

Show, m_ = 2, thread_id = 140176298325824

Call quick_exit()

ExitFunction4()

ExitFunction3()

ExitFunction2()

_Exit() (C++11 新增) 

[[noreturn]] void _Exit (int status) noexcept; 

如果不想在程序结束时,调用任何对象的 destructor、也不想执行任何由 atexit()、at_quick_exit() 注册的函数,则可使用 _Exit() 结束。 

exit() 结束 process 的过程中,除了调用 atexit() 注册的函数,还会 flush 并 close stdio stream。考虑一种情况,如果一个 parent process fork 出一个 child process,若 child process 使用 exit() 结束,child process 会强制 flush 残留在内存中的 stdio stream,而当 parent process 结束时,他也 flush 了 stdio stream,就会导致 flush 两次重复的结果。下面范例说明这种情况: 

#include <iostream>

#include <cstdlib>

#include <unistd.h>

#include <sys/types.h>

#include <sys/wait.h>

int main()

{

  std::cout << "Hello World";

  pid_t pid = fork();

  if (pid == 0) // child process

  {

    std::exit(0);

  }

  else if (pid > 0)

  {

    int status;

    waitpid(pid, &status, 0);

    std::cout << std::endl << "Child process has exited" << std::endl;

  }

  else

  {

    std::cerr << "fork failed" << std::endl;

  }

从下面执行的结果,可看到 Hello World 输出了两次,原因就在于 child process 执行的 exit() 触发了 fluch stdio stream。 

sora@sora-VirtualBox:~/cpp/c2$ clang++ -std=c++17 -stdlib=libc++ --pedantic-errors -pthread -o _Exit _Exit.cpp

sora@sora-VirtualBox:~/cpp/c2$ ./_Exit

Hello WorldHello World

Child process has exited

上述问题,只要将第 10 行改为调用 std::_Exit(0),就不会发生。 

fork() 的目的,是让 child process 与 parent 具有相同的内存内容、再执行不同的代码,所以 fork 前未摧毁的类、未 flush 的 stdio stream 等,都会带到 child process。这些类的 destructor,可能做了某些复杂的行为、不适合重复执行,而 stdio stream 也不适合 flush 重复的内容,在此情况下,就可考虑用 _Exit() 解决问题。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档