命名空间
变体
操作

std::exit

来自 cppreference.cn
 
 
 
 
定义于头文件 <cstdlib>
             void exit( int exit_code );
(C++11 前)
[[noreturn]] void exit( int exit_code );
(C++11 起)

导致程序正常终止。

执行几个清理步骤:

1) 销毁具有静态存储期的对象,并调用通过 std::atexit 注册的函数。
a) 具有静态存储期的非局部对象以其构造函数完成的逆序销毁。
b)std::atexit 注册的函数以其注册的逆序调用,但如果某个函数在注册时已经调用了任何先前注册的函数,则该函数将在这些函数之后被调用。
c) 对于每个用 std::atexit 注册的函数 f 和每个具有静态存储期的非局部对象 obj
  • 如果 fobj 初始化之前注册,f 只会在 obj 销毁之后被调用;
  • 如果 fobj 初始化之后注册,f 只会在 obj 销毁之前被调用。
d) 对于每个具有静态存储期的局部对象 objobj 的销毁方式,如同在 obj 构造函数完成时,注册了一个调用 obj 析构函数的函数到 std::atexit
(C++11 前)
1) 与当前线程关联的具有线程局部存储期的对象的析构函数、具有静态存储期的对象的析构函数,以及用 std::atexit 注册的函数并发执行,同时保持以下保证:
a) 最后一个线程局部对象的析构函数在第一个静态对象的析构函数之前定序
b) 如果线程局部或静态对象 A 的构造函数完成或动态初始化在线程局部或静态对象 B 之前定序,则 B 的销毁完成在 A 的销毁开始之前定序。
c) 如果静态对象 A 的初始化完成在针对某个函数 F 调用 std::atexit 之前定序,则在终止期间调用 F 在 A 的销毁开始之前定序。
d) 如果针对某个函数 F 调用 std::atexit 在静态对象 A 的初始化完成之前定序,则 A 的销毁开始在终止期间调用 F 之前定序。
e) 如果针对某个函数 F1 调用 std::atexit 在针对某个函数 F2 调用 std::atexit 之前定序,则在终止期间调用 F2 在调用 F1 之前定序。
(C++11 起)
  • 在上述情况中,
  • 如果任何用 `atexit` 注册的函数或任何静态/线程局部对象的析构函数抛出异常,则调用 std::terminate
  • 如果编译器选择将对象的动态初始化提升到非局部初始化的静态初始化阶段,则销毁的定序会遵循其原有的动态初始化顺序。
  • 如果一个函数局部(块作用域)静态对象被销毁,然后从另一个静态对象的析构函数中调用该函数,并且控制流通过该对象的定义(或者通过指针或引用间接使用),则行为未定义。
  • 如果一个函数局部(块作用域)静态对象在类或数组的子对象构造期间初始化,则它只在该类所有子对象或该数组所有元素都被销毁之后才会被销毁。
2) 所有 C 流都将被刷新和关闭。
3)std::tmpfile 创建的文件将被删除。
4) 控制权返回给宿主环境。如果 exit_code0EXIT_SUCCESS,则返回表示成功终止的实现定义状态。如果 exit_codeEXIT_FAILURE,则返回表示不成功终止的实现定义状态。在其他情况下,返回实现定义的状态值。

栈不会展开:具有自动存储期的变量的析构函数不会被调用。

目录

[编辑] 与 main 函数的关系

主函数返回,无论是通过 return 语句还是通过到达函数末尾,都会执行正常的函数终止(调用具有自动存储期的变量的析构函数),然后执行 std::exit,将 return 语句的参数(如果使用隐式返回则为 0)作为 exit_code 传递。

[编辑] 参数

exit_code - 程序的退出状态

[编辑] 返回值

(无)

[编辑] 示例

#include <cstdlib>
#include <iostream>
 
struct Static
{
    ~Static() 
    {
        std::cout << "Static destructor\n";
    }
};
 
struct Local
{
    ~Local() 
    {
        std::cout << "Local destructor\n";
    }
};
 
Static static_variable; // Destructor of this object *will* be called
 
void atexit_handler()
{
    std::cout << "atexit handler\n";
}
 
int main()
{
    Local local_variable; // Destructor of this object will *not* be called
    const int result = std::atexit(atexit_handler); // Handler will be called
 
    if (result != 0)
    {
        std::cerr << "atexit registration failed\n";
        return EXIT_FAILURE;
    }
 
    std::cout << "test\n";
    std::exit(EXIT_FAILURE);
 
    std::cout << "this line will *not* be executed\n";
}

输出

test
atexit handler
Static destructor

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
LWG 3 C++98 在清理期间,当 (1) 函数通过
std::atexit 注册或 (2) 静态局部对象初始化时,行为不明确。
已明确

[编辑] 参阅

导致程序异常终止(不进行清理)
(函数) [编辑]
注册一个在调用 std::exit() 时被调用的函数
(函数) [编辑]
导致程序快速终止而不完全清理
(函数) [编辑]
注册一个函数,在调用 std::quick_exit 时被调用
(函数) [编辑]
C 文档 关于 exit
English 日本語 中文(简体) 中文(繁體)