深入浅出 C++:与程序终止相关的函数 PART 1 - exit()、atexit()

C/C++ 程序,一般是借由 main() 的返回值调用 exit() 函数以正常结束程序。除了程序崩溃、或用户强制结束程序外,C++ 亦提供数个函数,允许调用以立即终止程序,本文将一一介绍这些函数。

不过,在进入主题前,需提醒读者:撰写程序时,尽可能使程序执行到 main() 结束为宜。C++ 在程序正常结束时,会负责清理所有产生的变量 (variable)、对象 (object),若以本文所介绍的函数强制终止程序,某些对象可能未完全摧毁而导致该执行的代码没有跑到。举例,程序中可能定义了某一对象处理临时文件,正常流程中,当对象的 destructor 执行时,临时文件会被删除,但若程序中以本文所列的函数终止程序,destructor 很可能未执行而留下临时文件而占用空间。

exit()

[[noreturn]] void exit(int exit_code);

函数宣告一开始的 [[noreturn]] 是 C++11 引进的 attribute,当函数的宣告/定义加上这个 attribute,代表不可能 return。若有一函数 A 调用了 exit(),则 exit() 并不会在结束时将控制权返还给 A。

请注意,“不可能 return” 与 “返回值类型为 void” 是两个截然不同的概念,”返回值类型为 void” 是能在函数结束时将控制权返还给调用端。

[[noreturn]] 能让 compiler 进行优惠,例如既然知道这个函数不会返回,记录返回地址的步奏就能免了;若发现调用 [[noreturn]] 函数的之后还有代码,也能直接消去这些不可能执行的部分以节省 compile 后的空间。

回到 exit()。它需要传入一个整数代表结束的状态,若传入 EXIT_SUCCESS (对应的整数为 0) 代表正常结束。

程序调用 exit() 函数后,仍是有部分代码会运行,为理解这个行为,下面范例中,MyClass 类的 constructor 与 destructor 执行时都输出文字,方便理解对象究竟是何时创建、何时调用 destructor 适当摧毁:

#include <iostream>
#include <string>
#include <cstdlib>
#include <thread>
#include <vector>

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("Print", m_);       }
private:
  int m_;
};

MyClass c1(1);
static MyClass c2(2);
thread_local MyClass c3(3);
thread_local MyClass c4(4);

int main()
{
  std::cout << "Begin of main()&
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值