1

我试图阅读从任何地方调用和return EXIT_SUCCESS;从任何地方调用之间的区别,到目前为止我发现的最好的资源是SO 上的这个答案。但是,我想澄清一个细节。main()exit(EXIT_SUCCESS)

对我来说,最有说服力的反对论点exit()(如那篇文章中所述)是在局部范围的对象上没有调用析构函数。但这对其他对象意味着什么?如果我exit()从其他地方调用,离main()方法堆栈很远,但是在只包含该调用且没有变量的块(甚至是方法)中调用怎么办?堆栈上其他地方的对象还会被破坏吗?

我的用例是这样的:

我有一个应用程序一直提示用户输入,直到给出“退出”命令(基于文本的冒险游戏)。实现这一目标的最简单方法是将“退出”映射到一个简单调用exit(EXIT_SUCCESS). 当然,我可以编写它,以便用户可以执行的每个操作都返回一个布尔值,指示游戏是否应该继续,然后就return false在我想退出时 - 但我唯一一次会返回除此之外的任何true内容方法 - 然后所有其他操作方法都必须return true只是因为我想避免exit()。另一方面,我创建了很多对象并动态分配了很多内存——所有这些都必须由类析构函数来处理,因此它们运行至关重要。

这里的最佳做法是什么?这是一个很好的案例exit(),还是和方法一样糟糕main

4

3 回答 3

3
if (command == "quit") {
    throw QuitGameException();
}

你可以抛出一个异常。异常将安全地展开堆栈并销毁所有调用者中的对象。

于 2013-01-08T21:42:48.020 回答
1

我什至不会读那个 SO 帖子,因为我知道它在说什么。不要使用 exit(),所以不要。

我知道使用 exit() 的一个原因 - 如果你完全注定要失败并且你无法很好地退出。在这种情况下,您不会以代码零退出。因此,无论如何,当您即将崩溃时,exit() 非零。

所有其他情况下,创建变量让您离开主循环并退出主循环,以清理所有内存。如果您不编写这样的代码,您将永远无法检测到所有内存泄漏。

于 2013-01-08T21:45:09.670 回答
1

堆栈上其他地方的对象还会被破坏吗?

不,exit() 执行以下操作(按顺序):

  • 与具有线程存储持续时间的当前线程关联的对象被销毁(仅限 C++11)。
  • 具有静态存储持续时间的对象被销毁 (C++) 并调用使用 atexit 注册的函数(如果抛出未处理的异常,则调用终止)。
  • 所有 C 流(使用 in 中的函数打开)都被关闭(如果被缓冲,则被刷新),并且所有使用 tmpfile 创建的文件都被删除。
  • 控制权返回宿主环境

来自:http ://www.cplusplus.com/reference/cstdlib/exit/

exit() 不展开堆栈,整个堆栈的内存被简单地释放,堆栈中单个对象的析构函数不运行。只有当所有没有简单析构函数的对象(不处理外部资源的对象)都分配在静态存储中(即全局变量或局部范围的静态变量)时,使用 exit() 才是安全的。大多数程序都有文件处理程序、套接字连接、数据库处理程序等,可以从更优雅的关闭中受益。请注意,动态分配的对象(不处理外部资源)不一定需要释放,因为程序无论如何都将终止。

exit() 是从 C 继承的一个特性,它没有析构函数,因此总是可以使用 atexit() 安排清理外部资源;一般来说,在 C++ 中安全地使用 exit() 是非常困难的,相反,在 C++ 中,您应该用 RAII 编写程序,并抛出异常以终止并进行清理。

于 2013-01-08T22:12:04.057 回答