我试图阅读return EXIT_SUCCESS;
与main()
之间的差异,并从任何地方调用exit(EXIT_SUCCESS)
,到目前为止我发现的最好的资源是这个答案。但是,有一个细节我想弄清楚。
对我来说,最令人信服的反对exit()
的论点(正如在那篇文章中提出的)是没有析构函数被调用到局部作用域的对象。但是这对于其他对象意味着什么?如果我从其他地方调用exit()
,从main()
方法的堆栈上相当远,但在块(甚至是一个方法),只包含该调用,没有变量?堆栈上其他地方的对象仍然会被销毁吗?
我的用例是:
我有一个应用程序,它一直提示用户输入,直到给出"退出"命令(基于文本的冒险游戏)。最简单的方法是将"quit"映射到一个只调用exit(EXIT_SUCCESS)
的方法。当然,我可以这样写,每个操作用户可以返回一个布尔值,指示游戏是否应该继续,然后只是return false
当我想退出-但只有时间我返回任何东西,但true
是从这个方法-每一个其他的动作方法将不得不return true
只是因为我想避免exit()
。另一方面,我创建了相当多的对象,动态地分配了相当多的内存——所有这些都必须由类析构函数来处理,所以它们的运行是至关重要的。
exit()
的好情况,还是像main
方法一样糟糕? if (command == "quit") {
throw QuitGameException();
}
可以抛出异常。异常将安全地展开堆栈并销毁所有调用方中的对象。
我甚至不会去读那篇SO帖子,因为我知道它在说什么。不要使用exit(),所以不要使用。
我知道使用exit()的一个原因——如果你已经彻底完蛋了,没有办法很好地退出。在这种情况下,您将而不是退出,代码为零。所以,当你要崩溃的时候,用非零的exit()
,创建变量,让你离开主循环和退出主循环,干净所有的内存。如果你不这样写代码,你将永远无法检测到所有的内存泄漏。
堆栈上其他地方的对象仍然会被析构吗?
不,exit()按顺序执行以下操作:
与具有线程存储时间的当前线程关联的对象将被销毁(仅限c++ 11)。具有静态存储持续时间的对象被销毁(c++),调用用atexit注册的函数(如果抛出未处理的异常,则调用terminate)。
- 所有C流(打开函数in)被关闭(和刷新,如果缓冲),并删除所有使用tmpfile创建的文件。
- 控制返回到主机环境
从:http://www.cplusplus.com/reference/cstdlib/exit/
exit()不展开堆栈,只是释放整个堆栈的内存,不运行堆栈中单个对象的析构函数。只有当所有没有简单析构函数的对象(不处理外部资源的对象)都被分配到静态存储(即全局变量或局部作用域的静态变量)中时,使用exit()才是安全的。大多数程序都有文件处理程序、套接字连接、数据库处理程序等,它们可以从更优雅的关闭中受益。注意,动态分配的对象(不处理外部资源)不一定需要释放,因为无论如何程序都即将终止。
exit()是继承自C语言的特性,C语言没有析构函数,因此可以使用atexit()安排外部资源的清理;一般来说,在c++中安全地使用exit()是非常困难的,相反,在c++中,您应该使用RAII编写程序,并抛出异常以终止并进行清理。