内存泄漏C ++

我只是用C ++编写了一些代码,但是当我运行valgrind时,它显示了一些可能的内存泄漏。 debugging代码到粒度级别我写了一个简单的C ++程序,如下所示:

#include<iostream> #include<cstdlib> using namespace std; int main() { std::string myname("Is there any leaks"); exit(0); } 

并在其上运行valgrind我得到:

 ==20943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 26 from 1) ==20943== malloc/free: in use at exit: 360,645 bytes in 12,854 blocks. ==20943== malloc/free: 65,451 allocs, 52,597 frees, 2,186,968 bytes allocated. ==20943== For counts of detected errors, rerun with: -v ==20943== searching for pointers to 12,854 not-freed blocks. ==20943== checked 424,628 bytes. ==20943== ==20943== LEAK SUMMARY: ==20943== definitely lost: 0 bytes in 0 blocks. ==20943== possibly lost: 917 bytes in 6 blocks. ==20943== still reachable: 359,728 bytes in 12,848 blocks. ==20943== suppressed: 0 bytes in 0 blocks. ==20943== Reachable blocks (those to which a pointer was found) are not shown. ==20943== To see them, rerun with: --show-reachable=yes 

然后,我感到我们已经强行退出(我在我的原始C + +代码中执行)。 现在问题是我想退出程序,因为我以前的旧代码等待新代码的退出状态。 例如,二进制a.out等待b.out的退出状态。 有没有办法避免内存泄漏,或者我应该真的担心内存泄漏,因为程序已经退出了。

这也给我提出了另一个问题,这样的代码有害吗?

 #include<stdio.h> #include<cstdlib> int main() { char *p=(char *)malloc(sizeof(char)*1000); exit(0); } 

如果你坚持使用exit()

 #include<iostream> int main(){ { std::string myname("Are there any leaks?"); } exit(0); } 

而且,当你从main返回时,返回的值就成为应用程序的退出代码。 所以如果你想传递一个退出代码,使用return exitCode;main()而不是exit

关于这一部分:

这也给我提出了另一个问题,这样的代码有害吗?

是的,因为这是一个糟糕的编程习惯。

操作系统会清理所有未能释放的内存,只要您没有设法清除所有系统内存和页面文件,就不会损坏操作系统。

然而,编写草率/漏码的代码可能会变成习惯,所以依靠操作系统清理你的烂摊子是一个坏主意。

使用return 0; 而不是exit(0);main结束。 exit的使用绕过了析构函数的执行。

这也给我提出了另一个问题,这样的代码有害吗?

 #include<stdio.h> int main() { char *p=(char *)malloc(sizeof(char)*1000); exit(0); } 

这对现代操作系统没有害处,因为当进程结束时它们会自动closures进程拥有的所有资源。

然而,这仍然是一个不好的做法,并且可能会导致微妙而难以发现的错误,因为在数年的维护过程中,代码会慢慢变化,直到一天,这确实会变成有害的。 我曾经在一些代码已经有十年的项目中工作过了,我从中学到了一些经验教训,其中一些很刺激。 因此,即使目前不存在问题,我也会避免编写这样的代码。

在大多数情况下,由于许多好的理由,您应该自己清理一下:更好的可维护性,更好的检查工具的实用性等等。

如果还有其他的function性的理由要清理,也许你的数据被保存到一个持久存储,那么你别无select – 你必须清理(尽pipe你可能想重新考虑你的devise)。

然而,在某些情况下,退出和“泄漏”可能会更好。

在程序结束时,你的程序将会退出。 当它这样做时,操作系统将恢复您的程序分配的任何内存,在某些情况下,它可以更快地执行此操作。

考虑一个大的链接列表,其中每个节点都是dynamic分配的,并且具有实质的dynamic分配结构。 要清理这个,你必须访问每个节点并释放每个有效载荷(这又可能导致其他复杂结构被散步)。

你最终可能会执行数百万次内存操作来运行这样的结构。

用户想要退出程序,他们坐在那里等待几十秒,等待一堆垃圾处理的发生。 他们不可能对结果感兴趣 – 毕竟他们正在放弃这个计划。

如果让这个“泄漏”,操作系统可以更快地回收分配给您的进程的整个内存块。 它不关心结构和任何对象清理。

http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

最终,你必须了解你的工具告诉你什么,确保你正确地使用它们。

为了避免内存泄漏,请从main返回状态,而不是调用exit 。 如果你返回零,你可以省略return语句,如果你喜欢; 在这种情况下,程序将退出状态为零。

这也给我提出了另一个问题,这样的代码有害吗?

在现代操作系统上,不会造成任何伤害 – 当程序终止时,所有资源都会自动回收。 但是,使用Valgrind这样的工具难以发现真正的问题,所以最好尽可能避免无害的内存泄漏。

 #include<iostream> using namespace std; int main() { { std::string myname("Is there any leaks"); } exit(0); } 

当你的进程实际上正在退出的时候,当main()退出时,操作系统将以任何方式回收分配给你的应用程序的所有资源。 你如何退出并不那么重要 – 至less在dynamic记忆方面。

如果你有一些分布式数据库连接打开或者什么的,你应该使用atexit()处理程序来closures它,强制终止直接退出可能会使它们不能运行,这将是不好的 – 但就你的操作系统资源而言,大概没事吧。

您还应该始终确保您释放(手动)文件locking和类似的事情,因为它们可能不会由于进程退出而消失。

如果您想要中断一个执行并传递一个不超过析构函数的返回码,请抛出一个exception,并从main()的exception中提取返回值。

如果程序正在退出,则不必担心使用mallocnew分配的malloc 。 操作系统会照顾它 – 只有在你的进程虚拟地址空间中的任何东西都会在进程死亡时消失。 如果你使用共享内存或命名pipe道,它可能仍然是一个问题。

添加不同的意见。

这样的代码并不是有害的。 当进程终止时,操作系统将会关心所有的事情。 其他一切都会导致操作系统不稳定。 只要确保你的持久数据(文件,…)是一致的。

要进一步和挑衅性地指出,明确释放程序退出的内存可能是有害的。

  1. 程序退出需要更长的时间(你有没有恼火等待一个程序退出,直到计算机closures?)
  2. 破坏的正确顺序并不总是微不足道的,特别是第三方组件(我记得有些程序在退出时可能会崩溃)
  3. 离开main (*)后,操作系统可能不会让你释放内存 ,而是杀死你的程序

你冒这个风险只是为了让Valgrind给你一个具体的产出吗?(**)


(*)

 #include<iostream> using namespace std; std::string myname("Is there any leaks"); int main() { exit(0); } 

(**)当然,没有“噪声”,任何内存分析仪的输出都会更有用。 在debugging模式下,只有在退出时明确释放内存呢?