tags:

views:

2741

answers:

15

This has been something that has bothered me for ages now.

We are all taught in school (at least, I was) that you MUST free every pointer that is allocated. I'm a bit curious, though, about the real cost of not freeing memory. In some obvious cases, like when malloc is called inside a loop or part of a thread execution, it's very important to free so there are no memory leaks. But consider the following two examples:

First, if I have code that's something like this:

int main()
  {
    char * a = (char *) malloc(1024);
    /* Do some arbitrary stuff with 'a' (no alloc functions) */
    return 0;
  }

What's the real result here? My thinking is that the process dies and then the heap space is gone anyway so there's no harm in missing the call to free (however, I do recognize the importance of having it anyway for closure, maintainability, and good practice). Am I right in this thinking?

Second, let's say I have a program that acts a bit like a shell. Users can declare variables like "aaa = 123" and those are stored in some dynamic data structure for later use. Clearly, it seems obvious that you'd use some solution that will calls some *alloc function (hashmap, linked list, something like that). For this kind of program, it doesn't make sense to ever free after calling malloc because these variables must be present at all times during the programs execution and there's no good way (that I can see) to implement this with statically allocated space. Is it bad design to have a bunch of memory that's allocated but only freed as part of the process ending? If so, what's the alternative?

Cheers

A: 

If you don't free up allocated memory when you no longer need it, your program will eventually run out of memory.

cdonner
-1 That is not the question
Tomas
Thanks, I don't think the question was what it is now when I answered it.
cdonner
+11  A: 

Yes you are right, your example doesn't do any harm (at least not on most modern operating systems). All the memory allocated by your process will be recovered by the operating system once the process exits.

Source: Allocation and GC Myths (PostScript alert!)

Allocation Myth 4: Non-garbage-collected programs should always deallocate all memory they allocate.

The Truth: Omitted deallocations in frequently executed code cause growing leaks. They are rarely acceptable. but Programs that retain most allocated memory until program exit often perform better without any intervening deallocation. Malloc is much easier to implement if there is no free.

In most cases, deallocating memory just before program exit is pointless. The OS will reclaim it anyway. Free will touch and page in the dead objects; the OS won't.

Consequence: Be careful with "leak detectors" that count allocations. Some "leaks" are good!

That said, you should really try to avoid all memory leaks!

Second question: your design is ok. If you need to store something until your application exits then its ok to do this with dynamic memory allocation. If you don't know the required size upfront, you can't use statically allocated memory.

compie
Does this answer get a special badge for accepted answer with negative votes?
Skizz
More to the point - *why* does it have negative votes? It's not a bad answer.
Kyle Cronin
Might be because the question, as I read it, is what is actually happening to the leaked memory, not whether this specific example is okay. I wouldn't vote it down though, because it's a still a good answer.
Probably that there were (early Windows, early Mac OS), and maybe still are, OSes which require processes to free memory before exit otherwise the space isn't reclaimed.
Pete Kirkham
NTDLS
I have an accepted answer that is currently sitting about -11, so he's not even in the running for the record.
Paul Tomblin
I think it is wrong to explain the need for free()'ing the memory by saying "because of the leak detector". This is like saying "you have to drive slowly in a play street because police men could be waiting for you with a speed camera".
phresnel
+45  A: 

Just about every modern operating system will recover all the allocated memory space after a program exits. The only exception I can think of might be something like Palm OS where the program's static storage and runtime memory are pretty much the same thing, so not freeing might cause the program to take up more storage. (I'm only speculating here.)

So generally, there's no harm in it, except the runtime cost of having more storage than you need. Certainly in the example you give, you want to keep the memory for a variable that might be used until it's cleared.

However, it's considered good style to free memory as soon as you don't need it any more, and to free anything you still have around on program exit. It's more of an exercise in knowing what memory you're using, and thinking about whether you still need it. If you don't keep track, you might have memory leaks.

On the other hand, the similar admonition to close your files on exit has a much more concrete result - if you don't, the data you wrote to them might not get flushed, or if they're a temp file, they might not get deleted when you're done. Also, database handles should have their transactions committed and then closed when you're done with them. Similarly, if you're using an object oriented language like C++ or Objective C, not freeing an object when you're done with it will mean the destructor will never get called, and any resources the class is responsible might not get cleaned up.

Paul Tomblin
+1 for mentioning other languages.
Brian R. Bondy
It's probably would be also good to mention that not everyone is using a modern operating system, if someone takes your program (and it still runs on an OS that does not recover memory) runs it then GG.
I really consider this answer wrong.One should always deallocate resources after one is done with them, be it file handles/memory/mutexs. By having that habit, one will not make that sort of mistake when building servers. Some servers are expected to run 24x7. In those cases, any leak of any sort means that your server will eventually run out of that resource and hang/crash in some way. A short utility program, ya a leak isn't that bad. Any server, any leak is death. Do yourself a favor. Clean up after yourself. It's a good habit. Yo momma don't work here no more.
EvilTeach
Which part of "However, it's considered good style to free memory as soon as you don't need it any more, and to free anything you still have around on program exit." do you consider wrong, then?
Paul Tomblin
It's not a style issue, it's a program defect. The fact that in many cases the leak is silent, does not magically turn it into a non-defect.
EvilTeach
If you have a memory store that you need right up until the moment the program exits, and you're not running on a primitive OS, then freeing the memory just before you exit is a stylistic choice, not a defect.
Paul Tomblin
+2  A: 

There's no real danger in not freeing your variables, but if you assign a pointer to a block of memory to a different block of memory without freeing the first block, the first block is no longer accessible but still takes up space. This is what's called a memory leak, and if you do this with regularity then your process will start to consume more and more memory, taking away system resources from other processes.

If the process is short-lived you can often get away with doing this as all allocated memory is reclaimed by the operating system when the process completes, but I would advise getting in the habit of freeing all memory you have no further use for.

Kyle Cronin
I want to say -1 for your first statement "there is no danger" except that you then give a thoughtful answer about why there IS danger.
As dangers go it's pretty benign - I'll take a memory leak over a segfault any day.
Kyle Cronin
Very true, and both of us would prefer neither =D
+3  A: 

It is completely fine to leave memory unfreed when you exit; malloc() allocates the memory from the memory area called "the heap", and the complete heap of a process is freed when the process exits.

That being said, one reason why people still insist that it is good to free everything before exiting is that memory debuggers (e.g. valgrind on Linux) detect the unfreed blocks as memory leaks, and if you have also "real" memory leaks, it becomes more difficult to spot them if you also get "fake" results at the end.

antti.huima
+1 for the Valgrind argument.
Stephan202
Does not Valgrind do a pretty good job distinguishing between "leaked" and "still reachable"?
Christoffer
-1 for "completely fine" It is bad coding practice to leave allocated memory without freeing it. If that code was extracted into a library, then it would cause memleaks all over the place.
-1 for "completely fine"
NTDLS
+4  A: 

If you're using the memory you've allocated, then you're not doing anything wrong. It becomes a problem when you write functions (other than main) that allocate memory without freeing it, and without making it available to the rest of your program. Then your program continues running with that memory allocated to it, but no way of using it. Your program and other running programs are deprived of that memory.

Edit: It's not 100% accurate to say that other running programs are deprived of that memory. The operating system can always let them use it at the expense of swapping your program out to virtual memory (</handwaving>). The point is, though, that if your program frees memory that it isn't using then a virtual memory swap is less likely to be necessary.

Bill the Lizard
+1  A: 

You are correct, memory is automatically freed when the process exits. Some people strive not to do extensive cleanup when the process is terminated, since it will all be relinquished to the operating system. However, while your program is running you should free unused memory. If you don't, you may eventually run out or cause excessive paging if your working set gets too big.

Michael
A: 

If you're developing an application from scratch, you can make some educated choices about when to call free. Your example program is fine: it allocates memory, maybe you have it work for a few seconds, and then closes, freeing all the resources it claimed.

If you're writing anything else, though -- a server/long-running application, or a library to be used by someone else, you should expect to call free on everything you malloc.

Ignoring the pragmatic side for a second, it's much safer to follow the stricter approach, and force yourself to free everything you malloc. If you're not in the habit of watching for memory leaks whenever you code, you could easily spring a few leaks. So in other words, yes -- you can get away without it; please be careful, though.

ojrac
+2  A: 

You are absolutely correct in that respect. In small trivial programs where a variable must exist until the death of the program, there is no real benefit to deallocating the memory.

In fact, I had once been involved in a project where each execution of the program was very complex but relatively short-lived, and the decision was to just keep memory allocated and not destabilize the project by making mistakes deallocating it.

That being said, in most programs this is not really an option, or it can lead you to run out of memory.

Uri
A: 

I think that your two examples are actually only one: the free() should occur only at the end of the process, which as you point out is useless since the process is terminating.

In you second example though, the only difference is that you allow an undefined number of malloc(), which could lead to running out of memory. The only way to handle the situation is to check the return code of malloc() and act accordingly.

mouviciel
+15  A: 

=== What about future proofing and code reuse? ===

If you don't write the code to free the objects, then you are limiting the code to only being safe to use when you can depend on the memory being free'd by the process being closed ... i.e. small projects.

If you do write the code that free()s all your dynamically allocated memory, then you are future proofing the code and letting others use it in a larger project.

Trevor Boyd Smith
A: 

In the real world application not freeing memory is running to overkill. Nothing works without following conventions.

lsalamon
+2  A: 

This code will work usually work allright, but consider the problem of code reuse.

You may have written some code snippet which doesn't free allocated memory, it is run in such a way that memory is then automatically reclaimed. Seems allright.

Then someone else copies your snippet into his project in such a way that it is executed one thousand times per second. That person now has a huge memory leak in his program. Not very good in general, usually fatal for a server application.

Code reuse is typical in enterprises. Usually the company owns all the code its employees produce and every department may reuse whatever the company owns. So by writing such "innocently-looking" code you cause potential headache to other people. This may get you fired.

sharptooth
+5  A: 

I typically free every allocated block once I'm sure that I'm done with it. Today, my program's entry point might be main(int argc, char *argv[]) , but tomorrow it might be foo_entry_point(char **args, struct foo *f) and typed as a function pointer.

So, if that happens, I now have a leak.

Regarding your second question, if my program took input like a=5, I would allocate space for a, or re-allocate the same space on a subsequent a="foo". This would remain allocated until:

  1. The user typed 'unset a'
  2. My cleanup function was entered, either servicing a signal or the user typed 'quit'

I can not think of any modern OS that does not reclaim memory after a process exits. Then again, free() is cheap, why not clean up? As others have said, tools like valgrind are great for spotting leaks that you really do need to worry about. Even though the blocks you example would be labeled as 'still reachable' , its just extra noise in the output when your trying to ensure you have no leaks.

Another myth is "If its in main(), I don't have to free it", this is incorrect. Consider the following:

char *t;

for (i=0; i < 255; i++) {
    t = strdup(foo->name);
    let_strtok_eat_away_at(t);
}

If that came prior to forking / daemonizing (and in theory running forever), your program has just leaked an undetermined size of t 255 times.

A good, well written program should always clean up after itself. Free all memory, flush all files, close all descriptors, unlink all temporary files, etc. This cleanup function should be reached upon normal termination, or upon receiving various kinds of fatal signals, unless you want to leave some files laying around so you can detect a crash and resume.

Really, be kind to the poor soul who has to maintain your stuff when you move on to other things .. hand it to them 'valgrind clean' :)

Tim Post
And yes, I once had a team mate tell me: "I never need to call free() in main()" <shudders>
Tim Post
A: 

You are correct, there is no point in free()-right-before-exit and it can be slow

There are various reasons for this:

  • All modern operating systems (and most legacy systems) have no trouble cleaning up and in fact are completely unaware of any program-internal data structures, including heaps.

  • Most (in fact virtually all) free() implementations do not ever return memory to the operating system anyway, so nothing other than a certain "academic purity" is even achieved by a free()-before-exit(). (Returning large blocks to the OS and then allocating them back is obviously slower than just leaving them in the heap.)

  • More importantly, it will always be slower and sometimes it can be considerably slower to reconstruct the heap than to just exit. If memory is paged out, it will simply be dropped on exit, but a series of free() calls (for most allocators) will result in demand paging all of it back in as each block is linked into the free list. This kind of I/O is outrageously slow and its random nature makes it hard for the OS to optimize reads of consecutive blocks. In addition to thrashing the disk it may also pointlessly evict useful cache blocks and replace them with useless links to memory that is about to become an anonymous list of unstructured pages. (And the CPU ops needed to do this are obviously wasted.)

For those who would bring up the possiblility of future code reuse to justify the certainty of pointless potentially expensive operations, I might suggest a debug mode and some test cases.

DigitalRoss
I once worked on a project where we spent a short amount of time trying to understand a programs memory usage (we were required to support it, we didn't write it). Based on the experience I anecdotally agree with your second bullet. However, I'd like to hear you (or someone) provide more proof that this is true.
Never mind, found the answer: http://stackoverflow.com/questions/1421491/does-calling-free-or-delete-ever-release-memory-back-to-the-system.Thank you SO!