[C++] 退出清理函数解读(exit、_exit、abort、atexit)

说明:在C++中,exit_exit(或_Exit)、abortatexit是用于控制程序退出和清理的标准库函数。下面是对这些函数的详细解读:

exit

  • 函数原型void exit(int status);
  • 作用exit函数用于正常退出程序。它会传递给操作系统一个退出状态码,通常用于指示程序成功完成(返回0)或发生错误(返回非0值)。
  • 清理操作exit会调用所有注册的atexit回调函数,这些函数按照注册的逆序执行,用于进行资源清理和释放。
  • 线程效应:调用exit会导致程序立即终止,所有线程都会被立即停止。

_exit 或 _Exit

  • 函数原型void _exit(int status);
  • 作用_exit(或_Exit,具体名称取决于平台)用于立即退出程序,与exit不同,它不会执行任何清理操作。
  • 特点:这个函数不会调用atexit注册的回调函数,也不会调用对象的析构函数,因此用于需要立即终止程序的情况。
  • 线程效应:与exit相同,_exit会导致所有线程立即停止。

abort

  • 函数原型void abort(void);
  • 作用abort函数用于异常退出程序,通常在捕获到严重错误时使用。它会导致程序立即终止,并且不会执行任何清理操作。
  • 信号abort会向操作系统发送SIGABRT信号,这可能导致操作系统生成核心转储(core dump),以供后续分析。
  • 线程效应abort会终止整个程序,包括所有线程。

atexit

  • 函数原型int atexit(void (*func)(void));
  • 作用atexit用于注册一个函数,该函数将在程序调用exit退出时被调用。这些函数按照注册的逆序执行。
  • 返回值:如果注册成功,返回0;如果注册失败(例如,因为达到注册函数的数量限制),返回非0值。
  • 限制:C++标准没有规定atexit可以注册的最大函数数量,但编译器通常会有一个限制。

按照常规的了解,程序结束已经有return操作可以控制,那么为什么还要引入退出相关函数呢?我们来继续看👇。

1 为什么引入退出相关函数

C++中引入exit_exit(或_Exit)、abortatexit这些函数是为了提供灵活的程序退出机制,以满足不同的程序终止需求。除了退出控制状态,还有其他引入的原因:

  • 资源清理exit在程序退出前会调用所有通过atexit注册的回调函数,这允许开发者执行必要的清理工作,如关闭文件、释放资源等,确保程序优雅地结束。

  • 立即终止程序_exit_Exit用于立即终止程序,不进行任何清理工作。这在需要快速退出程序,且不需要进行资源清理时非常有用。

  • 异常退出abort用于异常退出程序,通常在捕获到严重错误且无法恢复时使用。abort会导致程序立即终止,并且通常会生成核心转储(core dump),供开发者分析程序崩溃的原因。

  • 注册退出回调atexit允许开发者注册一个或多个回调函数,这些函数将在程序正常退出时被调用,从而执行必要的清理工作。

  • 兼容性exitatexit是从C语言继承而来的,它们在C++中得以保留,以确保与C代码的兼容性。

  • 处理未捕获的异常:当程序中发生未捕获的异常时,C++的异常处理机制会调用std::terminate,该函数默认行为是调用abort,但可以通过set_terminate函数自定义退出行为。

  • 多线程环境下的退出:在多线程程序中,可能需要在某个线程捕获异常后立即安全地退出整个程序,abort可以满足这一需求。

通过提供这些不同的退出函数,C++允许开发者根据程序的特定需求和上下文选择最合适的退出策略。

2 退出相关函数使用详解

以下是atexit、exit_exit和abort 这四个函数在不同场景下的示例代码。

2.1 atexit的使用示例

atexit的使用示例,代码实现如下:

#include <cstdlib>
#include <iostream>

void cleanupResources() {
    std::cout << "Cleaning up resources in atexit function." << std::endl;
}

void closeFiles() {
    std::cout << "Closing files in atexit function." << std::endl;
}

int main() {
    // 注册退出时的回调函数
    std::atexit(closeFiles);
    std::atexit(cleanupResources);
    std::cout << "Program is running." << std::endl;
    // 执行一些操作...
    // 当程序退出时,closeFiles 和 cleanupResources 将被调用
    return 0; // 正常退出程序
}

2.2 exit的使用示例

exit的使用示例,代码实现如下:

#include <cstdlib>
#include <iostream>

void cleanup() {
    std::cout << "Cleaning up resources." << std::endl;
}

int main() {
    std::atexit(cleanup); // 注册退出时的回调函数
    std::cout << "Program is running." << std::endl;
    // 执行一些操作...
    std::exit(EXIT_SUCCESS); // 正常退出程序
    return 0; // 这行代码不会被执行
}

2.3 _exit的使用示例

_exit的使用示例,代码实现如下:

#include <cstdlib>
#include <iostream>

int main() {
    std::cout << "Program is running." << std::endl;
    // 执行一些操作...
    _exit(EXIT_SUCCESS); // 立即退出程序,不执行任何清理
    // 以下代码不会被执行
    std::cout << "This will not be printed." << std::endl;
    return 0;
}

注意:此时即便是有atexit的注册函数,也不会执行。

2.4 abort的使用示例

abort的使用示例,代码实现如下:

#include <cstdlib>
#include <iostream>
#include <stdexcept>

int main() {
    try {
        // 模拟一个错误条件
        bool errorCondition = true;
        if (errorCondition) {
            throw std::runtime_error("A serious error occurred!");
        }
    } catch (const std::runtime_error& e) {
        std::cerr << "Caught an exception: " << e.what() << std::endl;
        std::abort(); // 异常退出,会生成核心转储
    }
    return 0; // 这行代码不会被执行
}

在这些示例中,exitatexit通常用于正常的程序退出流程,其中exit是显式退出程序,而atexit用于注册退出时需要调用的回调函数。_exit用于立即退出程序,不执行任何清理操作,通常用于紧急情况。abort用于异常退出,通常在捕获到不可恢复的错误时使用,它可能会导致操作系统生成核心转储文件。

  • 23
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值