首页 文章

main()中的return语句vs exit()

提问于
浏览
175

我应该在 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."你在该函数中创建的任何对象都不会被销毁 . 通常这没有任何影响,但有时它会像关闭文件一样(当然你希望所有数据都刷新到磁盘?) .

    请注意,即使您调用 exit() ,也会清除 static 对象 . 最后请注意,如果使用 abort() ,则不会销毁任何对象 . 也就是说,没有全局对象,没有静态对象,也没有本地对象会调用它们的析构函数 .

    Proceed with caution when favoring exit over return.

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

  • 4

    另一个区别: exit 是标准库函数,因此您需要包含 Headers 并与标准库链接 . 为了说明(在C中),这是一个有效的程序:

    int main() { return 0; }
    

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

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

    另外,这增加了一个额外的假设:从 main 调用 exit 具有与返回零相同的副作用 . 正如其他人所指出的那样,这取决于你调用 main 的可执行文件类型 . 您在编写使用C运行时的应用程序吗? Maya插件?一个Windows服务?一个司机?每个案例都需要研究,以确定 exit 是否等同于 return . 恕我直言使用 exit 当你真正的意思 return 只是让代码更混乱 . OTOH,如果你的意思是 exit ,那么一定要用它 .

  • 256

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

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

  • 14

    我总是使用 return 因为 main() 的标准原型说它确实返回 int .

    也就是说,某些版本的标准给予 main 特殊处理,并假设如果没有明确的 return 语句则返回0 . 给出以下代码:

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

    G仅为 foo() 生成警告,并忽略 main 中缺少的返回:

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

    我是 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() 中的程序是一个坏习惯 .

  • 4

    exit()是否做了“返回”没有的特殊事情?

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

    在这些情况下,标准要求具有相同的行为(具体而言,它表示返回 intmain() 兼容的东西应该等同于使用该值调用 exit() ) . 问题是不同的操作系统有不同的惯例来解释退出值 . 在许多(MANY!)系统上,0表示成功,其他任何事情都是失败 . 但就VMS而言,奇数值意味着成功,甚至意味着失败 . 如果从 main() 返回0,则VMS用户将看到有关访问冲突的令人讨厌的消息 . 实际上没有访问冲突 - 这只是与失败代码0相关联的标准消息 .

    然后ANSI出现并祝福 EXIT_SUCCESSEXIT_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程序,看起来像这样:

    #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 */
    }
    

    旁白:如果我没记错的话,退出值的VMS约定比奇数/偶数更细微 . 它实际上使用类似低三位的内容来编码严重性级别 . 然而,一般而言,奇怪的严重性级别表示成功或杂项信息,偶数表示错误 .

相关问题