奇怪的 内存 释放问题。delete 之后,内存无法释放

J_流儿 2018-02-02 06:44:02
#include <iostream>
#include <map>
using namespace std;

int main(int argc, char* argv[])
{
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]));
}
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;
return 0;
}


上面代码,运行到 26行的时候,内存不会释放,一直显示进程占用内存 2.9G。
但是如果 删除 第 16行,delete 之后,内存就恢复到 几十M了。

我尝试 MALLOC_MMAP_MAX_=1000000 MALLOC_MMAP_THRESHOLD_=1024 ./memtest
命令来运行 , 结果还是一样的。在 第16行存在的时候,内存一直无法释放。
...全文
1393 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
CrackWei 2021-05-23
  • 打赏
  • 举报
回复
J_流儿的回答是正确的。这种情况是因为内存并没有交还给系统,需要手动交还。 具体可以搜索SetProcessWorkingSetSize和EmptyWorkingSet这两个函数。 但是调用这两个函数只是“假“的交还。 目前没有更好的办法。
斯幽柏雷科技 2021-02-16
  • 打赏
  • 举报
回复
楼主解决了吗,我在win10下同样代码没问题,换linux也这样。。
J_流儿 2018-02-03
  • 打赏
  • 举报
回复
引用 12 楼 super_admi 的回复:
我用VS 2005/2008进一步测试发现: 如果是调试状态下,3G左右分配的内存,delete之后,并没有释放的迹象,而最后程序结束了,似乎才慢慢释放内存; 如果直接运行编译好的exe程序(DEBUG版本和RELEASE版本都试过),则3G内存被delete之后,内存占用明显快速减少,最后大约只有100多M的占用,考虑到map还没释放,应该是可以理解的。 所以,我不清楚楼主是不是在调试状态下查看内存的,我这里明显就是调试器的问题。
不清楚是不是和调试器有关系,我后面没有在Windows 下继续测试了。上面的那个解释应该八九不离十了。准备去看下源码再说了
super_admi 2018-02-03
  • 打赏
  • 举报
回复
我用VS 2005/2008进一步测试发现: 如果是调试状态下,3G左右分配的内存,delete之后,并没有释放的迹象,而最后程序结束了,似乎才慢慢释放内存; 如果直接运行编译好的exe程序(DEBUG版本和RELEASE版本都试过),则3G内存被delete之后,内存占用明显快速减少,最后大约只有100多M的占用,考虑到map还没释放,应该是可以理解的。 所以,我不清楚楼主是不是在调试状态下查看内存的,我这里明显就是调试器的问题。
J_流儿 2018-02-03
  • 打赏
  • 举报
回复
这个问题我自己现在能够解释到的是: 1、内存并没有泄露,只是没有归还给系统。如果在这段程序 的后面 继续分配内存的话,进程的heap 是不会继续增加的。 2、中间的tMap 申请的内存破坏了 空闲内存的连续性,导致 进程一直没有办法 凑够一块完整的内存(在ptmalloc2上,堆顶的连续空闲内存到达64k以上,才会主动归还内存给OS,不然就是自己管理。在不同的编译器上效果可能不一样。) 3、更详细的细节,关于怎么分配的,如何影响的还没有一个结果,内存管理太复杂了。
J_流儿 2018-02-03
  • 打赏
  • 举报
回复
引用 7 楼 super_admi 的回复:
我这里测试情况如下: 1.WIN10+GCC 32位:内存爆掉; 2.减少一个数量级,WIN10+GCC 32位,分配正常,释放正常; 3.WIN7 + VS 2005 64位:分配正常,释放时卡死。内存分配完成,应用程序大约占了3G多,而不是楼主说的2.9G。
不同的编译器内存分配方式不一样吧,2.9G 是在 Cent OS 6.8上看到的结果。
super_admi 2018-02-03
  • 打赏
  • 举报
回复
楼上搞笑吧?你以为是在栈上分配的内存?还是有自动内存管理?
cutmelon 2018-02-03
  • 打赏
  • 举报
回复
这个不存在内存泄漏问题啊,简单来说就是作用域问题,有临时变量没有释放而已,贴两段代码自己体会一下吧,注意注释掉的花括号
#include <iostream>
#include <map>
using namespace std;

int main(int argc,char* argv[])
{
	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]));
			}
		}
		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;
	return 0;
}
#include <iostream>
#include <map>
using namespace std;

int main(int argc,char* argv[])
{
	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]));
//			}
		}
		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;
	return 0;
}
一般在函数中使用按楼主原来写法没什么问题,如果要严格控制内存,参考上面的代码
super_admi 2018-02-03
  • 打赏
  • 举报
回复
我这里测试情况如下: 1.WIN10+GCC 32位:内存爆掉; 2.减少一个数量级,WIN10+GCC 32位,分配正常,释放正常; 3.WIN7 + VS 2005 64位:分配正常,释放时卡死。内存分配完成,应用程序大约占了3G多,而不是楼主说的2.9G。
paschen 版主 2018-02-03
  • 打赏
  • 举报
回复
一些系统在一些情况下对释放的内存可能并不立即被系统收回,而只是进行相应的标记,在程序下一次申请时可直接使用,从而提高效率,但在系统需要内存且内存不足时这部分内存才被系统回收
J_流儿 2018-02-02
  • 打赏
  • 举报
回复
引用 5 楼 paschen 的回复:
在WIN10测试没有发现不会释放,注释不注释那句都会减少到70M
不同的编译器好像效果不一样,clang 在某些情况下会出现,Windows 只在 VisualStudio2010 上 出现过。 gcc 一直都会有,不过我现在改了代码之后,可以释放一半儿,剩下一半儿还是无法释放。貌似知道什么原因,但是还解释不了。还在继续研究
paschen 版主 2018-02-02
  • 打赏
  • 举报
回复
在WIN10测试没有发现不会释放,注释不注释那句都会减少到70M
J_流儿 2018-02-02
  • 打赏
  • 举报
回复
引用 3 楼 zjq9931 的回复:
试验了一下,确实如此。 不过在map的作用域结束的时候,内存会慢慢释放掉。
有发现过这种现象,只是没有搞清楚这两者之间相互影响的细节
  • 打赏
  • 举报
回复
试验了一下,确实如此。 不过在map的作用域结束的时候,内存会慢慢释放掉。
J_流儿 2018-02-02
  • 打赏
  • 举报
回复
引用 1 楼 super_admi 的回复:
分配和释放内存,减少一个数量级试试。
目前内存分配不大,总共也才 2.9G。 试了下。 减少一个数量级也没用
super_admi 2018-02-02
  • 打赏
  • 举报
回复
分配和释放内存,减少一个数量级试试。

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧