Wednesday, March 23, 2011

Why does my c program not free memory as it should?

I have made a program in c and wanted to see, how much memory it uses and noticed, that the memory usage grows while normally using it (at launch time it uses about 250k and now it's at 1.5mb). afaik, I freed all the unused memory and after some time hours, the app uses less memory. Could it be possible, that the freed memory just goes from the 'active' memory to the 'wired' or something, so it's released when free space is needed? btw. my machine runs on mac os x, if this is important.

From stackoverflow
  • How do you determine the memory usage? Have you tried using valgrind to locate potential memory leaks? It's really easy. Just start your application with valgrind, run it, and look at the well-structured output.

    Nino : eeehm .. i just started activity monitor.app and watched how much memory it uses.
    Konrad Rudolph : The reason I asked is that monitor.app and similar applications don't show the real memory usage reliably. Zan has pointed out one of the reasons for that.
    Aaron Maenpaa : Valgrind is an awesome tool +1.
  • What kind of application is it?

    Third Party stuff also tends to have memory leaks. (GUIs and whatnot).

    I second Konrad Rudolphs proposal.

  • If you're looking at the memory usage from the OS, you are likely to see this behavior. Freed memory is not automatically returned to the OS, but normally stays with the process, and can be malloced later. What you see is usually the high-water mark of memory use.

    As Konrad Rudolph suggested, use something that examines the memory from inside the process to look for memory links.

  • The C library does not usually return "small" allocations to the OS. Instead it keeps the memory around for the next time you use malloc.

    However, many C libraries will release large blocks, so you could try doing a malloc of several megabytes and then freeing it.

  • On OSX you should be able to use MallocDebug.app if you have installed the Developer Tools from OSX (as you might have trouble finding a port of valgrind for OSX).

    /Developer/Applications/PerformanceTools/MallocDebug.app

    Nino : mallocdebug.app doesn't seem to allow network connections, and as my application handles network requests, it's difficult to see how much memory it allocates after a request
  • I agree with what everyone has already said, but I do want to add just a few clarifying remarks specific to os x:

    First, the operating system actually allocates memory using vm_allocate which allocates entire pages at a time. Because there is a cost associated with this, like others have stated, the C library does not just deallocate the page when you return memory via free(3). Specifically, if there are other allocations within the memory page, it will not be released. Currently memory pages are 4096 bytes in mac os x. The number of bytes in a page can be determined programatically with sysctl(2) or, more easily, with getpagesize(2). You can use this information to optimize your memory usage.

    Secondly, user-space applications do not wire memory. Generally the kernel wires memory for critical data structures. Wired memory is basically memory that can never be swapped out and will never generate a page fault. If, for some reason, a page fault is generated in a wired memory page, the kernel will panic and your computer will crash. If your application is increasing your computer's wired memory by a noticeable amount, it is a very bad sign. It generally means that your application is doing something that significantly grows kernel data structures, like allocating and not reaping hundreds of threads of child processes. (of course, this is a general statement... in some cases, this growth is expected, like when developing a virtual host or something like that).

  • In addition to what the others have already written:

    malloc() allocates bigger chunks from the OS and spits it out in smaller pieces as you malloc() it. When free()ing, the piece first goes into a free-list, for quick reuse by another malloc if the size fits. It may at this time be merged with another free item, to form bigger free blocks, to avoid fragmentation (a whole bunch of different algorithms exist there, from freeLists to binary-sized-fragments to hashing and what not else). When freed pieces arrive so that multiple fragments can be joined, free() usually does this, but sometimes, fragments remain, depending on size and orderof malloc() and free(). Also, only when a big such free block has been created will it be (sometimes) returned to the OS as a block. But usually, malloc() keeps things in its pocket, dependig on the allocated/free ratio (many heuristics and sometimes compile or flag options are often available).

    Notice, that there is not ONE malloc/free algotrithm. There is a whole bunch of different implementations (and literature). Highly system, OS and library dependent.

0 comments:

Post a Comment