main函数结束后还能执行其他函数?

在 main 函数结束后执行的函数或代码通常被称为”终止处理程序”(termination handler)或”退出处理程序”(exit handler)。这个概念在不同的上下文中可能有不同的具体名称:

  • 退出函数(Exit function)
    当使用 std::atexit() 注册时,这个函数通常被称为”退出函数”。
  • 终止处理程序(Termination handler)
    特别是在使用 std::set_terminate() 设置处理未捕获异常的函数时。
  • 析构函数(Destructor)
    当使用全局对象的析构函数来执行清理操作时。
  • 清理函数(Cleanup function)
    这是一个通用术语,经常用来描述这类函数的功能。
  • 信号处理函数(Signal handler)
    当使用信号处理机制(如处理 SIGINT)来执行程序结束时的操作。
  • 终结器(Finalizer)
    这个术语有时用于描述在程序结束时执行最终清理的函数。
  • 钩子函数(Hook function)
    在某些上下文中,这种在特定时刻(如程序退出时)自动执行的函数被称为”钩子”。
  • atexit 处理程序(atexit handler)
    特指通过 std::atexit() 注册的函数。
  • 程序终止函数(Program termination function)
    一个更正式的术语,描述在程序终止时执行的函数。
  • 延迟加载函数(Deferred function)
    在一些编程语言和环境中,这种在程序结束时执行的函数被称为”延迟”执行的函数。

尽管没有一个统一的官方术语,但在 C++ 编程中,”退出函数”(exit function)或”清理函数”(cleanup function)是最常用的术语。选择使用哪个术语通常取决于具体的上下文和个人或团队的偏好。在技术文档或代码注释中,使用这些术语中的任何一个都是可以的,只要能清楚地表达其功能即可。

示例

以下为几种实现不同的方法介绍。

析构函数 destructor

attribute
这是 GCC 的一个扩展语法,用于向编译器传达特殊的信息或指令。

这个属性告诉编译器,被标记的函数应该在程序结束时自动调用。它的行为类似于 C++ 全局对象的析构函数。

最简单易用的方式,但是不属于标准特性,并非所有编译器都支持,代码移植性可能会降低。

  • 当程序正常终止(main 函数返回或调用 exit())时,标记为 destructor 的函数会被自动调用,不需要在main函数中做任何修改。
  • 这些函数的调用顺序与它们的定义顺序相反。
  • 多个 destructor 函数可以共存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

void __attribute__((destructor)) cleanup1() {
std::cout << "Cleanup 1 executed" << std::endl;
}

void __attribute__((destructor)) cleanup2() {
std::cout << "Cleanup 2 executed" << std::endl;
}

int main() {
std::cout << "Main function executing" << std::endl;
return 0;
}

输出

1
2
3
Main function executing
Cleanup 2 executed
Cleanup 1 executed

扩展

  • constructor

    该语法与destructor相反,用于main函数执行之前调用。

信号处理函数

用于处理程序信号异常时的善后工作,或者其他处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <csignal>

void signalHandler(int signum) {
std::cout << "Interrupt signal (" << signum << ") received.\n";
// your code
exit(signum);
}

int main(int argc, char *argv[])
{
signal(SIGINT, signalHandler);
//...

return 0;
}

退出函数(Exit function)

使用 std::atexit() 注册时,这个函数通常被称为”退出函数”,也是比较简单易用的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <cstdlib>

void cleanup() {
std::cout << "Performing cleanup operations..." << std::endl;
// clean up.
}

int main() {
// register exit func
std::atexit(cleanup);

// main code

return 0;
}

钩子函数(Hook Function)

  • TODO