C++ 中的 new/delete 导致奇怪的内存泄漏
Posted
技术标签:
【中文标题】C++ 中的 new/delete 导致奇怪的内存泄漏【英文标题】:Strange Memory leak by new/delete in C++ 【发布时间】:2018-02-02 10:05:32 【问题描述】:下面是我的问题和代码:
-
当代码运行到第26行时,这个进程获得的内存没有返回给OS?
但是,如果我删除第16行,内存会被正确释放吗?
我知道这不是使用这么多小内存块的常规方式,但我很想知道原因。
我用MALLOC_MMAP_MAX_=1000000 MALLOC_MMAP_THRESHOLD_=1024,
运行了这个程序,但没有任何改变。
int i = 0;
std::cout << "waitting for input, you can check current memory" << std::endl;
std::cin >> i;
char** ptr = new char *[1000000];
std::map<int, char *> tMap;
for (unsigned long i = 0; i < 1000000; i ++)
ptr[i] = new char[3000];
tMap.insert(make_pair(i, ptr[i])); //line 16
std::cout << "waitting for input, you can check current memory" << std::endl;
std::cin >> i;
for (unsigned long i = 0; i < 1000000; i ++)
delete []ptr[i];
delete []ptr;
std::cout << "waitting for input, you can check current memory" << std::endl;
std::cin >> i; //line 26
return 0;
这里的资料比较多,我查过tMap的内存,不到100M。
1、分配内存并停止,检查内存资源:
holds 2.9G memory
2、释放内存并停止,检查内存资源:
holds 2.9G memory
【问题讨论】:
你怎么知道的? 请注意,您周围有几个名为i
的变量,这很危险,可能会导致编译器使用您认为会使用的另一个变量。它在这里可能很好用,但这是一种危险的习惯,避免它。
【参考方案1】:
C++ 没有垃圾回收,因此保留一个额外的指针副本不会阻止内存被释放。
delete[] ptr[i]
之后发生的事情是地图充满了无法再使用的悬空指针。
另一个想法:您可能看到的内存泄漏是tMap
也分配动态内存来存储插入的数据。当地图超出范围时,该内存将被释放,就在第 27 行之后。
【讨论】:
感谢您的回答,我检查了tMap的内存,与100万个3000字节的块相比,这没什么大不了的。我添加了两张图片来显示内存状态。希望这将有助于解释我的问题。【参考方案2】:1、当代码运行到第26行时,该进程获得的内存没有返回给OS?
不能保证任何内存都会被 C++ 程序释放到操作系统,因为它被程序正确地分配了 delete
d。在许多 C++ 运行时中,被删除的动态分配内存仍将保留同一程序供将来使用,而不是释放给操作系统。 GCC/Linux 是编译器/运行时环境的一个示例,其中更大的分配通常在共享内存段中完成,这些内存段可以在程序终止之前释放给操作系统,以便操作系统或其他程序可以使用它们。
2、但是,如果我删除第16行,内存会被正确释放吗?
第 16 行对稍后在第 22 行删除/释放内存没有任何影响(这可能会将其返回到应用程序稍后可能重新分配的动态内存池,或实际将其释放给操作系统正如刚才提到的)。不过,它确实涉及对 std::map
元素本身的更多动态分配。
请注意,tMap
析构函数本身不会delete
或以任何方式释放内存。要自动释放内存(通过类似指针的变量或容器),请使用 智能指针,例如 std::shared_ptr
或 std::unique_ptr
(您可以在 Google 上搜索相关信息)。
【讨论】:
感谢您的回答,有一些关键词可能会有很大帮助。通过分配大内存块而不是许多小块已经避免了这个问题。我发布这个问题只是为了了解 C 或 C++ 内存管理的一些细节。 大页面是好的。仍然:“问题已被避免” - 这实际上是一个重大问题吗?操作系统倾向于使用 virtual memory 并将某些磁盘配置为 swap - 发生的情况是您的程序已分配但最近未使用的内存内容(并且所有已删除的内存都不应该一直在使用,直到新的分配重新使用)可以复制到磁盘,然后分配给其他程序的物理内存。一般来说,只有当你发现你的电脑速度慢到无法接受时,这才是真正的问题,而不仅仅是因为top
或ps
中的内存使用数字看起来很吓人......
你是对的。记忆还在这里。删除后,我尝试分配更多内存,但堆不再增长。最合理的解释是 tMap 将内存块分开,很难找到大于指定大小的连续块,然后没有内存返回给操作系统。我将继续研究细节。非常感谢您的帮助。以上是关于C++ 中的 new/delete 导致奇怪的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章
C++ 中的 new/delete 和 new[]/delete[]深入理解