我注意到/bin
和/usr/bin
中的FreeBSD代码有一些修复使用exit
代替return
,这意味着什么?
我想到的只是return
语句可能导致vfork(2)
破坏堆栈帧,这是唯一的原因吗?如果这是真的,那么为什么只有/bin
和/usr/bin
中的一部分命令得到修复,而不是所有命令?
答案 0 :(得分:1)
如果main函数的返回类型是与int兼容的类型,则从初始调用返回main函数等效于调用exit函数,并将main函数返回的值作为其参数
这排除了你的破坏了堆栈框架理论;对于符合C的实现,return 0;
在功能上与exit(0);
相同(至少对于非递归main
入口点而言。)
我认为这种改变只是风格上的,或者可能是由无知引导的。另一种可能性是作者希望将main
转换为递归函数(或者main
已经变成递归函数; idk,我只是做了一个快速的grep而且看起来不像立即递归)。最后,作为最后一个严峻的替代方案,也许FreeBSD使用的C实现是不符合的(我当然希望不是!)......
编辑:我刚刚通过阅读this answer来了解这可能是编译器错误的解决办法,但是我检查了源代码的使用情况{ {1}}并且没有理由继续进行这种推理。
答案 1 :(得分:1)
让我们看看我是否可以将其他人提供的各种链接合并到一个合适的答案中。
As far as the C language is concerned, there is no difference.
致电exit()
atexit()
; tmpfile()
; 来自main的return <n>
相当于exit( <n> )
。
Some flawed static code analyzers think different.
就C语言而言,由main()
而不是free()
d分配的内存泄露。 Unix在进程中清理终止,但并非所有操作系统都做(!)。
显然,一些静态代码分析器认为仍然在exit()
点分配的内存没有泄露(当它们从return
执行main()
时,这就是提交的原因(以消除警告)。
这是代码分析器中错误的解决方法。
As far as the C++ language is concerned, there is a lot of difference.
当您从return
main()
时,您将离开该函数的范围,这意味着本地对象将被销毁。
由于C ++程序员享受确定性破坏的好处(与Java相反,即使在VM终止时也可能执行或不执行析构函数......),他们倾向于使他们的析构函数不仅仅是释放内存。网络连接,临时文件,由ncurses
锁定的终端窗口,所有这些优点,C程序员必须手动关注或使用atexit()
。
当您从main()
致电std::exit()
时,该功能会直接将控制权转交给运行时。 main()
函数永远不会返回,进程终止,而调用main()
的析构函数 - 本地对象。
此外,虽然std::exit()
被定义为刷新并关闭 C 输出流,但没有 C ++ 输出流< / em>的
答案 2 :(得分:0)
在我看来,这并不是一个非常好的理由。
这个特殊的变化在freebsd邮件列表的this post中讨论。
简短的说法是提交日志应该是
&#34;使用exit()代替main()中的return来解决破坏的静态分析器&#34;
因此,它可以帮助静态分析器和内存分析器,否则它会将main()中分配的内容报告为内存泄漏 - 大多数简单的实用程序都不会因为进程而需要解除分配。无论如何要退出。