内存泄漏C++

Glo*_*ior 45 c c++ valgrind memory-leaks

我刚刚在C++中编写了一个代码进行字符串操作的代码,但是当我运行valgrind时,它显示了一些可能的内存泄漏.将代码调试到粒度级别我编写了一个简单的C++程序,如下所示:

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

并运行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
Run Code Online (Sandbox Code Playgroud)

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

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

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

swe*_*egi 65

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

  • 例如,使用return 12应该返回与exit(12)相同的退出状态到操作系统,除了它干净地退出. (38认同)
  • 只是为了澄清这一点,@ Piyush - *不,你不需要调用exit*.正如JohnB所说,从main返回的整数被用作退出状态 - 这就是它的用途. (10认同)

Sig*_*erm 63

如果你坚持使用exit():

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

此外,从main返回值返回时,将成为应用程序的退出代码.因此,如果要传递退出代码,请使用return exitCode;in main()而不是exit.

关于那部分:

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

是的,因为这是一个坏的编程习惯.

操作系统将清除您未能释放的任何内存,因此只要您没有设法占用所有系统内存和页面文件,就不应该损坏操作系统.

但是,编写草率/漏洞代码可能会变成习惯,因此依靠操作系统来清理混乱是一个坏主意.

  • 专业提示:假设您正在使用Death Station 9000,这是一台主要操作系统从小猫的大脑中分配内存的计算机,并且只有在被明确告知时才将其恢复.此外,任何未定义行为的实例都将导致地球的破坏. (72认同)
  • 操作系统**可能会清理内存,但实际上并不能保证这样做(尽管通常会这样做). (14认同)
  • @SigTerm这不是关于保存3行代码.我很欣赏你的建议如何适用于初学者程序员,但是有一个阶段你可以做得更好.为什么Firefox需要30秒才能关闭?因为它是关于清理操作系统可以在几毫秒内丢弃的东西的肛门,并且因为当前的编程语言不区分可选的资源解除分配和强制终结(例如刷新缓冲区).你建议我们放弃并清理一切.我建议我们尽可能地努力一点. (5认同)
  • 只有糟糕的操作系统才会这样做.除非另有证明,否则代码通常很糟糕. (4认同)
  • @SigTerm:对于那些不想争辩的人,你似乎在做很多争论:) (3认同)
  • 内存在进程的虚拟内存空间中分配,操作系统通常无法查看在此空间内进行的分配(据我所知).当进程退出时,其虚拟空间随后被释放回系统; 只有严重破坏的操作系统才会这样做. (2认同)
  • @KazDragon你能以某种方式激励这个吗?在操作系统即将更有效地执行操作之前清理内存是非常愚蠢的.你正在浪费时间,可能会将所有最近未使用过的内存从交换中释放出来,然后释放它,将关机时间增加一百倍.我想到一个操作系统如此糟糕以至于无法清理死机进程的内存,如果你找到一个,那么我会感到不寒而栗,那么_that_需要修复,而不是你的程序. (2认同)
  • @SigTerm:我完全不同意你的意见.我还发现"专业提示"的介绍不必要地傲慢和居高临下.这不是一个专家小贴士,对于那些对自己的错误不安全的人来说,这是一个提示.你无权对此发表权威,至少在这种情况下,你错了. (2认同)

sbi*_*sbi 22

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

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

它对现代操作系统没有害处,因为它们会在流程结束时自动关闭流程拥有的所有资源.

然而,它仍然是不好的做法,并且可能导致微妙且难以发现错误,经过几年的维护,代码慢慢变化,直到白天,这确实变得有害.我曾参与一些代码已有十年历史的项目,并且我已经学到了一些教训,其中一些相当苛刻.因此,即使目前没有出现问题,我也会避免编写这样的代码.

  • 但是对于代码的维护者来说,这可能是有害的,他们将更难以使用像valgrind这样的工具来追踪合法的问题. (27认同)

Rob*_*Rob 5

在大多数情况下,由于已经给出了许多好的理由,因此值得自行清理:更好的可维护性,更好的检查工具实用性等等.

如果还有其他功能原因需要清理,可能您的数据会保存到持久存储中,那么您别无选择 - 您必须清理(尽管您可能需要重新考虑您的设计).

但是,在某些情况下,退出并"泄漏"可能会更好.

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

考虑一个大的链表,其中每个节点都是动态分配的,并带有一个实质上动态分配的结构.要清理它,您必须访问每个节点并释放每个有效负载(这反过来可能导致其他复杂结构被移动).

您最终可能会执行数百万次内存操作以运行此类结构.

用户想要退出程序,他们会在那里停留10秒钟,等待一堆垃圾处理发生.他们不可能对结果感兴趣 - 毕竟他们正在退出计划.

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

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

最终,您必须了解您的工具告诉您的内容,确保您正确使用它们.