内存泄漏使用malloc失败

时间:2010-08-17 07:22:09

标签: c linux memory

我正在编写一个泄漏内存(主内存)的程序,以测试系统在低系统内存和交换内存时的行为方式。我们使用以下循环定期运行并泄漏内存

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 Daemon FAILED由于可用内存不足......”。但是当我运行命令“free”时,我可以看到运行该程序对主内存或交换没有影响。

我做错了吗?

6 个答案:

答案 0 :(得分:8)

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

如果你有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)
    /* ... */

如果您有较旧的内核,则必须触摸分配中的每个页面。

答案 1 :(得分:3)

可能存在某种写时复制优化。我建议实际上在你正在分配的内存中写一些内容。

答案 2 :(得分:1)

正在发生的事情是malloc从堆中请求argmem * 256页(假设页面大小为4 KB)。堆反过来从操作系统请求内存。但是,所有这一切都是在页表中为新分配的内存块创建条目。除了堆跟踪malloc请求所需的物理RAM之外,没有为该进程分配实际的物理RAM。

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

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

所以,你最好的策略是分配你的大块RAM,然后以4096字节的间隔写一些东西。

答案 3 :(得分:0)

ulimit -m -v打印什么?

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

答案 4 :(得分:0)

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

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

在不知道您的操作系统是什么以及您正在尝试测试的内容的情况下,很难提出具体的建议,但您可能希望查看比malloc()更多的低级别内存分配方式,或者控制虚拟内存系统。在Linux上,您可能需要查看mlock()

答案 5 :(得分:0)

我认为caf已经解释过了。 Linux通常配置为允许过度使用内存。你分配了大量的内存,但内部却没有发生任何事情,只是记下你处理过的大量内存。在您尝试编写该块之前,内核不会尝试查找可用的虚拟内存来满足读/写访问。这有点像航班预订:航空公司通常超量预订航班,因为总有一部分乘客没有出现。

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