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