关于C++:在main()中的return和exit()

return statement vs exit() in main()

我应该在main()中使用exit()还是仅使用return语句?就我个人而言,我喜欢return语句,因为我觉得它就像在读取代码时读取任何其他函数和流控制一样(在我看来)。即使我想重构main()函数,拥有return似乎比exit()更好。

exit()有没有做过return没有做过的特别的事情?


事实上,这是有区别的,但很微妙。它对C++有更多的含义,但差异是很重要的。

当我在main()中调用return时,将为本地作用域对象调用析构函数。如果我调用exit(),就不会为本地作用域对象调用析构函数!重读一遍。exit()不返回。这意味着一旦我调用它,就不会有"倒退",任何在函数中创建的对象都不会被破坏。这通常没有任何影响,但有时确实如此,比如关闭文件(确实需要将所有数据刷新到磁盘?).

注意,即使调用exit()static对象也将被清除。最后要注意,如果使用abort(),则不会销毁任何对象。也就是说,不调用全局对象、静态对象和本地对象的析构函数。

当倾向于退出而不是返回时,请小心操作。

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a


另一个区别是:exit是一个标准库。功能,因此需要包括标题并与标准链接图书馆。为了说明(在C++中)这是一个有效的程序:

1
int main() { return 0; }

但要使用exit,您需要一个包括:

1
2
#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

另外,这又增加了一个假设:从main调用exit与返回零具有相同的副作用。正如其他人指出的,这取决于您正在构建的可执行文件的类型(即,谁在调用main)。您是否在编写使用C运行时的应用程序?一个玛雅插件?Windows服务?司机?每一个案例都需要研究,看看exit是否等同于return。imho使用exit,当您真正指return时,只会使代码更加混乱。哦,如果你真的是指exit,那就用它吧。


至少有一个理由更喜欢exit:如果您的任何atexit处理程序引用main中的自动存储持续时间数据,或者使用setvbufsetbufmain中的自动存储持续时间缓冲区分配给其中一个标准流,那么从main返回将产生未定义的但调用exit是有效的。

另一个潜在的用法(通常为玩具程序保留)是退出具有递归调用main的程序。


Does exit() do anything special that 'return' doesn't?

对于一些不常见平台的编译器,exit()可能会将其参数转换为程序的退出值,而从main()返回的值可能会直接传递给主机环境而不进行任何转换。

在这些情况下,标准要求相同的行为(具体来说,它说返回与main()兼容的int应该等同于使用该值调用exit()。问题是不同的操作系统在解释退出值时有不同的约定。很多(很多!)系统,0意味着成功,任何其他都是失败。但在虚拟机上,零碎的价值观意味着成功,偶而的价值观意味着失败。如果从main()返回0,vms用户将看到有关访问冲突的恶意消息。实际上没有访问冲突——这只是与失败代码0相关联的标准消息。

后来,安西来了,祝福以东十一〔6〕和以东十一〔7〕作为可以传给以东十一〔0〕的论据。该标准还指出,exit(0)的行为应该与exit(EXIT_SUCCESS)相同,因此大多数实现将EXIT_SUCCESS定义为0

因此,标准将您置于VM上的绑定中,因为它没有留下返回值为0的失败代码的标准方法。

因此,20世纪90年代早期的vax/vms c编译器没有解释main()的返回值,它只是将任何值返回到主机环境。但是,如果使用exit(),它将按照标准要求执行:将EXIT_SUCCESS0转换为成功代码,将EXIT_FAILURE转换为一般故障代码。使用EXIT_SUCCESS时,必须传给exit(),不能从main()退回。我不知道该编译器的现代版本是否保留了这种行为。

一个可移植的C程序,用于如下显示:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>

int main() {
  printf("Hello, World!
"
);
  exit(EXIT_SUCCESS);  /* to get good return value to OS */
  /*NOTREACHED*/ /* to silence lint warning */
  return 0;  /* to silence compiler warning */
}

旁白:如果我记得正确的话,退出值的vms约定比奇数/偶数更微妙。它实际上使用像低位三位这样的东西来编码严重性级别。但是,一般来说,奇数严重级别表示成功或杂项信息,偶数严重级别表示错误。


我强烈支持R关于使用exit()的评论,以避免在程序实际结束之前回收main()中的自动存储。main()中的return X;语句并不完全等同于对exit(X);的调用,因为当main()返回时,main()的动态存储消失了,但如果调用exit()则不会消失。

此外,在C语言或任何C语言中,return语句强烈地提示读者,执行将继续在调用函数中进行,而如果计算调用main()函数的C启动例程,这种执行的继续在技术上通常是正确的,但当您打算结束t时,它并不完全是您的意思。他处理。

毕竟,如果您想从除main()以外的任何其他函数中结束程序,必须调用exit()。在main()中持续这样做也会使代码更易于阅读,而且也使任何人都更容易重新考虑代码;即,从main()复制到其他函数的代码不会因为意外的return语句而出现错误行为,这些语句本应是exit()调用。

因此,将所有这些观点结合起来,得出的结论是,使用return语句结束main()中的程序是一个坏习惯,至少对于C来说是这样。


我总是使用return,因为main()的标准原型表示它确实返回了int

也就是说,一些版本的标准对main进行了特殊处理,如果没有明确的return声明,则假定返回0。给出以下代码:

1
2
int foo() {}
int main(int argc, char *argv[]) {}

g++只为foo()生成警告,忽略main缺少的返回:

1
2
3
% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo():
foo.cc:1: warning: control reaches end of non-void function