我应该在 main() 中使用 exit() 还是仅使用 return 语句?我个人赞成 return 语句,因为我觉得's like reading any other function and the flow control when I'读代码很顺利(在我看来) . 即使我想重构 main() 函数,让 return 似乎是比 exit() 更好的选择 .
exit() 做了 return 没有做的任何特别的事情吗?
6 回答
22
实际上,存在差异,但它很微妙 . 它对C有更多的影响,但差异很重要 .
当我在 main() 中调用 return 时,将为我的本地作用域对象调用析构函数 . 如果我拨打 exit() , no destructor will be called for my locally scoped objects! 重新阅读 . exit()does not return . 这意味着一旦我调用它,就会有"no backsies."你在该函数中创建的任何对象都不会被销毁 . 通常这没有任何影响,但有时它会像关闭文件一样(当然你希望所有数据都刷新到磁盘?) .
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, World!\n");
exit(EXIT_SUCCESS); /* to get good return value to OS */
/*NOTREACHED*/ /* to silence lint warning */
return 0; /* to silence compiler warning */
}
6 回答
实际上,存在差异,但它很微妙 . 它对C有更多的影响,但差异很重要 .
当我在
main()
中调用return
时,将为我的本地作用域对象调用析构函数 . 如果我拨打exit()
, no destructor will be called for my locally scoped objects! 重新阅读 .exit()
does not return . 这意味着一旦我调用它,就会有"no backsies."你在该函数中创建的任何对象都不会被销毁 . 通常这没有任何影响,但有时它会像关闭文件一样(当然你希望所有数据都刷新到磁盘?) .请注意,即使您调用
exit()
,也会清除static
对象 . 最后请注意,如果使用abort()
,则不会销毁任何对象 . 也就是说,没有全局对象,没有静态对象,也没有本地对象会调用它们的析构函数 .Proceed with caution when favoring exit over return.
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
另一个区别:
exit
是标准库函数,因此您需要包含 Headers 并与标准库链接 . 为了说明(在C中),这是一个有效的程序:但要使用
exit
,你需要一个包括:另外,这增加了一个额外的假设:从
main
调用exit
具有与返回零相同的副作用 . 正如其他人所指出的那样,这取决于你调用main
的可执行文件类型 . 您在编写使用C运行时的应用程序吗? Maya插件?一个Windows服务?一个司机?每个案例都需要研究,以确定exit
是否等同于return
. 恕我直言使用exit
当你真正的意思return
只是让代码更混乱 . OTOH,如果你的意思是exit
,那么一定要用它 .至少有一个理由更喜欢
exit
:如果您的任何atexit
处理程序在main
中引用自动存储持续时间数据,或者您使用setvbuf
或setbuf
分配给其中一个标准流,则自动存储持续时间缓冲区在main
,然后从main
返回产生未定义的行为,但调用exit
是有效的 .另一个潜在用法(通常为玩具程序保留)是从具有
main
的递归调用的程序退出 .我总是使用
return
因为main()
的标准原型说它确实返回int
.也就是说,某些版本的标准给予
main
特殊处理,并假设如果没有明确的return
语句则返回0 . 给出以下代码:G仅为
foo()
生成警告,并忽略main
中缺少的返回:我是 STRONGLY 第二条R.关于使用exit()的评论,以避免在程序实际结束之前回收
main()
中的自动存储 .main()
中的return X;
语句并不完全等同于对exit(X);
的调用,因为main()
的动态存储在main()
返回时消失,但如果调用exit()
则不会消失 .此外,在C或任何类C语言中,
return
语句强烈暗示读者将在调用函数中继续执行,而如果计算调用main()
函数的C启动例程,则执行的继续执行通常在技术上是正确的,当你打算结束这个过程时,这并不是你的意思 .毕竟,如果你想从除
main()
之外的任何其他函数中结束你的程序,你必须调用exit()
. 在_1578388中持续这样做也可以使您的代码更具可读性,并且它还使任何人都可以更轻松地重新编写代码 . 即从main()
复制到某个其他函数的代码不会因为意外的return
语句而行为不当,这些语句应该是exit()
调用 .因此,将所有这些要点结合在一起得出的结论是,至少对于C来说,使用
return
语句来结束main()
中的程序是一个坏习惯 .有一些编译器不常见的平台,
exit()
可能会将其参数转换为程序的退出值,而从main()
返回可能只是将值直接传递给主机环境而不进行任何转换 .在这些情况下,标准要求具有相同的行为(具体而言,它表示返回
int
与main()
兼容的东西应该等同于使用该值调用exit()
) . 问题是不同的操作系统有不同的惯例来解释退出值 . 在许多(MANY!)系统上,0表示成功,其他任何事情都是失败 . 但就VMS而言,奇数值意味着成功,甚至意味着失败 . 如果从main()
返回0,则VMS用户将看到有关访问冲突的令人讨厌的消息 . 实际上没有访问冲突 - 这只是与失败代码0相关联的标准消息 .然后ANSI出现并祝福
EXIT_SUCCESS
和EXIT_FAILURE
作为你可以传递给exit()
的参数 . 该标准还说exit(0)
应该与exit(EXIT_SUCCESS)
的行为相同,因此大多数实现将EXIT_SUCCESS
定义为0
.因此,该标准使您对VMS进行绑定,因为它没有留下标准方法来返回碰巧具有值0的失败代码 .
因此,20世纪90年代早期的VAX / VMS C编译器没有解释
main()
的返回值,它只是向主机环境返回任何值 . 但是如果您使用了exit()
它将执行标准所需的操作:将EXIT_SUCCESS
(或0
)转换为成功代码,并将EXIT_FAILURE
转换为通用故障代码 . 要使用EXIT_SUCCESS
,您必须将其传递给exit()
,您无法从main()
返回它 . 我不知道该编译器的更多现代版本是否保留了该行为 .一个便携式C程序,看起来像这样:
旁白:如果我没记错的话,退出值的VMS约定比奇数/偶数更细微 . 它实际上使用类似低三位的内容来编码严重性级别 . 然而,一般而言,奇怪的严重性级别表示成功或杂项信息,偶数表示错误 .