简体   繁体   English

内存泄漏使用malloc失败

[英]Memory Leak Using malloc fails

I am writing a program to leak memory( main memory ) to test how the system behaves with low system memory and swap memory. 我正在编写一个泄漏内存(主内存)的程序来测试系统在低系统内存和交换内存时的行为方式。 We are using the following loop which runs periodically and leaks 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 );
        }

}

Above loop runs for sometime and prints the message "leakyapp Daemon FAILED due to insufficient available memory...." . 上面的循环运行一段时间并打印消息“leakyapp Daemon FAILED由于可用内存不足......”。 But when I run the command "free" I can see that running this program has no effect either on Main memory or Swap. 但是当我运行命令“free”时,我可以看到运行该程序对主内存或交换没有影响。

Am I doing something wrong ? 难道我做错了什么 ?

Physical memory is not committed to your allocations until you actually write into it. 在您实际写入之前,物理内存不会提交给您的分配。

If you have a kernel version after 2.6.23, use mmap() with the MAP_POPULATE flag instead of malloc() : 如果在2.6.23之后有内核版本,请使用带有MAP_POPULATE标志的mmap()而不是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)
    /* ... */

If you have an older kernel, you'll have to touch each page in the allocation. 如果您有较旧的内核,则必须触摸分配中的每个页面。

There might be some sort of copy-on-write optimization. 可能存在某种写时复制优化。 I would suggest actually writing something to the memory you are allocating. 我建议实际上写一些东西给你正在分配的内存。

What is happening is that malloc requests argmem * 256 pages from the heap (assuming a 4 Kbyte page size). 发生的事情是malloc从堆请求argmem * 256页(假设页面大小为4 KB)。 The heap in turn requests the memory from the operating system. 堆反过来从操作系统请求内存。 However, all that does is create entries in the page table for the newly allocated memory block. 但是,所有这一切都是在页表中为新分配的内存块创建条目。 No actual physical RAM is allocated to the process, except that required by the heap to track the malloc request. 除了堆跟踪malloc请求所需的物理RAM之外,没有为该进程分配实际的物理RAM。

As soon as the process tries to access one of those pages by reading or writing, a page fault is generated because the entry in the page table is effectively a dangling pointer. 一旦进程尝试通过读取写入访问其中一个页面,就会生成页面错误,因为页面表中的条目实际上是一个悬空指针。 The operating system will then allocate a physical page to the process. 然后,操作系统将为该进程分配一个物理页面。 It's only then that you'll see the available physical memory go down. 只有这样你才能看到可用的物理内存下降。

Since all new pages start completely zeroed out, Linux might employ a "copy on write" strategy to optimise page allocation. 由于所有新页面都开始完全清零,因此Linux可能会采用“写入时复制”策略来优化页面分配。 ie it might keep a single page totally zeroed and always allocate that one when a process tries to read from a previously unused page. 即,它可能会使单个页面完全归零,并且当进程尝试从先前未使用的页面读取时始终分配该页面。 Only when the process tries to write to that new page would it actually allocate a completely fresh page from physical RAM. 只有当进程尝试写入该新页面时,它才会实际从物理RAM分配一个完全新鲜的页面。 I don't know if Linux actually does this, but if it does, merely reading from a new page is not going to be enough to increase physical memory usage. 我不知道Linux是否真的这样做,但如果确实如此,仅仅从新页面读取不足以增加物理内存使用量。

So, your best strategy is to allocate your large block of RAM and then write something at 4096 byte intervals throughout it. 所以,你最好的策略是分配你的大块RAM,然后以4096字节的间隔写一些东西。

What does ulimit -m -v print? ulimit -m -v打印什么?

Explanation: On any server OS, you can limit the amount of resources a process can allocate to make sure that a single runaway process can't bring down the whole machine. 说明:在任何服务器操作系统上,您可以限制进程可以分配的资源量,以确保单个失控进程无法关闭整个计算机。

I'm guessing (based on the command line argument) that you're using a desktop/server OS and not an embedded system. 我猜测(基于命令行参数)您使用的是桌面/服务器操作系统,而不是嵌入式系统。

Allocating memory like this is probably not consuming much RAM. 像这样分配内存可能不会消耗太多RAM。 Your memory allocation might not have even succeeded - on some OSs (eg Linux), malloc() can return non-NULL even when you ask for more memory than is available. 您的内存分配可能甚至没有成功 - 在某些操作系统(例如Linux)上,即使您要求的内存多于可用内存, malloc()也可以返回非NULL。

Without knowing what your OS is and exactly what you're trying to test, it's difficult to suggest anything specific, but you might want to look at more low level ways of allocating memory than malloc() , or ways of controlling the virtual memory system. 在不知道您的操作系统是什么以及您正在尝试测试的内容的情况下,很难建议任何特定的内容,但您可能希望查看比malloc()更多低级别的内存分配方式,或者控制虚拟内存系统的方法。 On Linux you might want to look at mlock() . 在Linux上你可能想看看mlock()

I think caf already explained it. 我认为caf已经解释过了。 Linux is usually configured to allow overcommitting memory. Linux通常配置为允许过度使用内存。 You allocate huge chunks of memory, but internally there happens nothing but just making a note that you process wants this huge chunk of memory. 你分配了大量的内存,但内部却没有发生任何事情,只是记下你处理过的大量内存。 It's not before you try to write that chunk, that the kernel tries to find free virtual memory to satisfy the read/write access. 在您尝试编写该块之前,内核不会尝试查找可用的虚拟内存来满足读/写访问。 This is a bit like flight booking: Airlines usually overbook the flights, because there's always a percentage of passengers who do not show up. 这有点像航班预订:航空公司通常会超额预订航班,因为总有一部分乘客没有出现。

You can force the memory to be committed by writing to the chunk with memset() after allocation. 您可以通过在分配后使用memset()写入块来强制提交内存。 calloc should work too. calloc应该工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM