2010-08-17 78 views
2

我正在编写一个程序来泄漏内存(主内存)来测试系统如何与低系统内存和交换内存的行为。我们使用下面的循环周期性运行,并出现内存泄漏内存泄漏使用malloc失败

main(int argc, char* argv[]) 
{ 
    int arg_mem = argv[1]; 

     while(1) 
     { 
      u_int_ptr =(unsigned int*) malloc(arg_mem * 1024 * 1024); 

     if(u_int_ptr == NULL) 
      printf("\n leakyapp Daemon FAILED due to insufficient available memory...."); 

      sleep(arg_time); 
     } 

} 

上述循环运行了一段时间,并打印消息“leakyapp守护进程失败,因为可用内存不足......”。但是当我运行“free”命令时,我可以看到运行该程序对主内存或交换没有任何影响。

我做错了什么?

回答

7

只有在实际写入之前,物理内存才会提交给您的分配。

如果您2.6.23之后有一个内核版本,使用mmap()MAP_POPULATE标志,而不是malloc()

u_int_ptr = mmap(NULL, arg_mem * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0); 

if (u_int_ptr == MAP_FAILED) 
    /* ... */ 

如果你有一个旧的内核,你必须触及每一页的分配。

+0

我觉得“不”,在最后一行应删除:-) – Job 2010-08-17 07:54:20

+0

我改变了我的代码,因此我宣布一个阵列来存储所有指针 的char *一[1000]; 而在while循环 u_int_ptr = MMAP(NULL,arg_mem * 1024 * 1024,PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE,-1,0); A [1] =(字符*)u_int_ptr; //触摸页面* a [i] ='A'; i ++; 但我仍面临着同样的问题。 – Poorna 2010-08-17 08:13:47

+0

它在内存上执行memset后工作 – Poorna 2010-08-17 16:14:06

0

什么是ulimit -m -v的打印?

说明:在任何服务器操作系统上,您可以限制进程可以分配的资源量,以确保单个失控进程无法关闭整个计算机。

+0

它显示 最大内存大小(千字节,-m)无限 虚拟内存(千字节,-v)无限 – Poorna 2010-08-17 07:32:03

+0

在这种情况下,我的回答并不能帮助:-) – 2010-08-17 07:40:36

3

可能有某种写时复制优化。我会建议实际写一些东西给你正在分配的内存。

0

我猜(基于命令行参数)你使用的是桌面/服务器操作系统而不是嵌入式系统。

像这样分配内存可能不会消耗太多内存。您的内存分配可能甚至没有成功 - 在某些操作系统(例如Linux)上,即使您询问的内存比可用内存多,malloc()也可以返回非NULL值。

不知道你的操作系统是什么,也不知道你想要测试什么,很难建议任何具体的东西,但是你可能想要看看比malloc()更低级别的分配内存的方式,或者控制虚拟内存系统。在Linux上,你可能想看看mlock()

+0

我使用的SUSE Linux企业版。 – Poorna 2010-08-17 07:56:30

0

我想caf已经解释过了。 Linux通常配置为允许过度使用内存。你分配了大量的内存,但是内部没有任何事情发生,只是做了一个说明,你的进程需要这么大的内存。在您尝试写入该块之前,内核试图找到免费的虚拟内存以满足读/写访问。这有点像航班预订:航班通常是overbook的航班,因为总有一部分乘客没有出现。

您可以通过在分配后向memset()写入块来强制提交内存。 calloc也应该工作。

1

发生了什么是malloc从堆中请求argmem * 256页(假设页面大小为4 KB)。堆又从操作系统请求内存。但是,所做的只是在新分配的内存块的页表中创建条目。除了堆需要跟踪malloc请求之外,没有实际的物理RAM被分配给进程。

只要过程试图通过读取写入访问其中一个页面,就会生成页面错误,因为页表中的条目实际上是一个悬挂指针。然后操作系统将为进程分配一个物理页面。只有这样你才能看到可用的物理内存下降。

由于所有新页面开始完全归零,Linux的可能采用的策略是“写入时复制”优化页分配。即它可以保持单个页面完全归零,并且当进程试图从先前未使用的页面读取时总是分配该页面。只有当进程试图写入新页面时,实际上它才会从物理RAM中分配一个全新的页面。我不知道Linux是否真的这样做,但如果是这样,仅仅从新页面读取内容不足以增加物理内存使用量。

所以,最好的策略是分配的内存大块,然后在它整个4096个字节间隔写的东西。