Now there are also issues that are specific to C++.
C + + 在退出函数时(return-ing)比 C 执行更多的工作。具体来说,它调用超出范围的局部对象的析构函数。在大多数情况下,程序员不会太关心进程停止后程序的状态,因此它不会有太大的不同: 分配的内存将被释放,文件资源关闭等等。但是,如果析构函数执行 IOs,那么这可能很重要。例如,本地创建的自动 C + + OStream不会在调用退出时刷新,您可能会丢失一些未刷新的数据(另一方面,静态 OStream将被刷新)。
如果您使用的是老式的 C FILE*流,那么这种情况就不会发生。这些将在 exit()上冲洗。实际上,规则是相同的,对于已注册的退出函数,FILE*将在所有正常终止时刷新,包括 exit(),但不调用 _exit()或 abort ()。
您还应该记住,C + + 提供了第三种方法来摆脱函数: 抛出异常。函数 威尔调用析构函数的这种方式。如果在调用者链的任何地方都没有捕获到异常,那么异常可以上升到 main ()函数并终止进程。
exit()表示要立即停止当前进程。当我们遇到某种不可恢复的问题,使您的代码无法再做任何有用的事情时,它可以用于错误管理。当控制流程复杂且错误代码必须向上传播时,这通常很方便。但是请注意,这是不好的编码实践。在大多数情况下,无声地结束流程是最糟糕的行为,实际的错误管理应该是首选的(或者在 C + + 中使用异常)。
In C, there's not much difference when used in the startup function of the program (which can be main(), wmain(), _tmain() or the default name used by your compiler).
如果你在 main()中使用 return,控制权就会回到最初启动程序的 C 库中的 _start()函数,然后它还是会调用 exit()。所以你用哪个真的不重要。
After executing gcc -S -O1. Here what I found watching
在装配时(只有重要部件) :
main:
movl $0, %eax /* setting return value */
ret /* return from main */
还有
main:
subq $8, %rsp /* reserving some space */
movl $0, %edi /* setting return value */
call exit /* calling exit function */
/* magic and machine specific wizardry after this call */
The other mechanism is to invoke atexit() with a function that accesses data from main() — via a pointer. This is harder to set up as the functions called via the atexit() mechanism are not given any arguments. So, you have to do something like this:
static void *at_exit_data = 0;
static void at_exit_handler(void)
{
char *str = at_exit_data;
printf("Exiting: %s\n", str);
}
int main(void);
{
char buffer[] = "Message to be printed via functions registered with at_exit()";
at_exit_data = buffer;
at_exit(at_exit_handler);
…processing…
return 0;
}
Again, the buffer pointed at by at_exit_data has ceased to exist when the program returned from main() and so the handler function invokes undefined behaviour.