LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   To free() or not to free() before an exit() ? (https://www.linuxquestions.org/questions/programming-9/to-free-or-not-to-free-before-an-exit-458107/)

introuble 06-25-2006 07:03 AM

To free() or not to free() before an exit() ?
 
Should you free() all alloc'd buffers before calling exit()? Why (not)?

Flesym 06-25-2006 08:10 AM

You do not need to free your memory before exit. During the termination of the process the kernel also deletes the memory mappings which were associated with that process. So everything is "freed" implicit by the kernel.

jlinkels 06-25-2006 08:27 AM

I think it is better practice to free everything before your program terminates. One important advantage I can imagine is that when you run those utilities to detect memory leaks, they will return exactly zero bytes of allocated memory before exiting the program. When you leave memory allocated at the end of the program you never know whether you have a leak.

Besides, if you have a function where you allocate memory, you have to free allocated memory anyway before you return. (Unless you pass the pointer back to the caller). Main () is just another function, so why not follow this behavior?

jlinkels

taylor_venable 06-25-2006 09:09 AM

I agree with both points. While it's not necessary, it is good practice. Calling free() is kind of like putting curly braces around the body of "if" statements - it's not always necessary, but if you get into the habit of doing it, it will never come back to bite you.

primo 06-26-2006 01:19 AM

Quote:

Originally Posted by taylor_venable
curly braces around the body of "if" statements

It's best to put them even when you call functions. You never know if they are macros that were poorly defined.

It's always better to do a explicit free(). If you were to extend the program with atexit() handlers, the fact that some memory should/shouldn't be available may be an issue. They're called when you use the exit() call, so don't count on the OS to the work for you.

Flesym 06-26-2006 06:46 AM

Quote:

Originally Posted by jlinkels
Besides, if you have a function where you allocate memory, you have to free allocated memory anyway before you return. (Unless you pass the pointer back to the caller). Main () is just another function, so why not follow this behavior?

Who said, that exit() has to be called by main()?? Consider a (common) case, where function A allocates some memory and calls function B, which then calls exit(). If you want to free all the memory which was allocated until this exit(), you would have to hold track of every block of data (on the heap) that the programm uses so far. How do you want to achieve this? -Do you pass pointers to these blocks as parameters to every function that my call exit()? Now consider, you build another function C which also allocates some memory and calls B, too. You would have to change B in such a way, that it also frees the data of function C...., an this is just a very simple case (imagine you have some complicated case of indirect recursion!)

So my advice still is to not loose yourself in such a fussy (and needless, as I mentioned in my first post) memory tracking.

Quote:

Originally Posted by primo
It's best to put them even when you call functions. You never know if they are macros that were poorly defined.

Yeah! -And don't forget to put your armor on before you go to sleep; you never know if a comet will hit you! ;-)

jtshaw 06-26-2006 07:37 AM

Quote:

Originally Posted by Flesym
Who said, that exit() has to be called by main()?? Consider a (common) case, where function A allocates some memory and calls function B, which then calls exit(). If you want to free all the memory which was allocated until this exit(), you would have to hold track of every block of data (on the heap) that the programm uses so far. How do you want to achieve this? -Do you pass pointers to these blocks as parameters to every function that my call exit()? Now consider, you build another function C which also allocates some memory and calls B, too. You would have to change B in such a way, that it also frees the data of function C...., an this is just a very simple case (imagine you have some complicated case of indirect recursion!)

With the exception of the case where you exit based on a signal handler well designed program flow should allow you to always free the memory you allocate at some point. Not being careful with this when you design software in C is how you end up with nasty memory leaks.

Anyway.. for my answer to the original question... it is always best where possible to free memory you allocate. You never know when you might end up coming back to your code later and incorporating it into a bigger program and forget you didn't do all your memory accounting in the past.

jlinkels 06-26-2006 06:55 PM

Writing programs which exit in nested functions is generally considered as bad programming practice. You should leave functions at the return statement, not somewhere in the middle.

You are right that if your program receives a SIGHUP, it is killed in the middle, and you have to leave cleanup to the OS. However, this is not normal practice. The program ought to be WRITTEN such that it leaves nicely at the end of main. And has cleaned up all the garbage.

If you make it a practice to leave your program somewhere in the middle, leaving it to the OS to clean up your memory allocations, and you ever have to find a memory leak, I wish you lots of good luck.

BTW, Primo might overdo it with curly braces around everything, but this can be considered defense or robust programming. Better check twice, we all make errors, others make (more) errors, the unexpected happens. That is why it is possible to make a program in plain old C behave like it is bug free. And that is why most GUI based programs, written in an OO language, with zillions of things assumed and not checked or double armed starts to behave oddly sooner or later.

jlinkels

tuxdev 06-26-2006 07:35 PM

For a shell programming assignment, calling exit() within the function that handled all of my ridiculously simple builtins in order to (obviously) implement the builtin 'exit' was the simplest thing to do that does the right thing. The major question I would have is if doing a free of all your memory yourself is going to be slower than letting the kernel do it for you. Maybe the best option is to write the code within a #ifndef NDEBUG block. It might help to apply RAII to C code as best as you can.

Flesym 06-27-2006 03:10 AM

Quote:

Originally Posted by jlinkels
You are right that if your program receives a SIGHUP, it is killed in the middle, and you have to leave cleanup to the OS. However, this is not normal practice. The program ought to be WRITTEN such that it leaves nicely at the end of main. And has cleaned up all the garbage.

I agree, that it's a much better style to let the process end itself after returning of main, but then you don't have to call exit(), which was made to terminate your program somewhere in the middle (and this is was the question was about). Surely, you can free everything by hand, but I think it isn't worth a thought (of course, only before and exit()!) and unless it really is the most trivial case, I don't see any significant advantages. The argument of finding memory leaks isn't that strong; actually I find it quite easy to identify and classify them with the help of modern tools. And because this analysis have to be done in any case (as you said: "We all make errors"), you don't loose much time.

And yes, defensive programming is a very good thing! But I think even here are limits; if you convulsive try to hold your defense in any possible case, you may forget what you actually are fighting for. A defensive pattern in programming is only useful, if it avoids hard detectable (thus time consuming) bugs and errors which may relatively often occur. Your brace-if was a good example for this. But the brace-function-call to avoid bad macros.... First I don't use a macro unless I don't know what it does and second I never (in almost 15 years of programming experience) came across such a macro that would make i possible to put it between braces (at least I don't remember). -Surely everyone can construct such one, but fact is, that they must be very, very rare in the real world and putting every function call between braces is definitely not worth the effort - maybe it's defensive but it's no good style!

My conclusions of this:
Yes I agree, that a program flow should be clear designed and it is desirable to be able to free memory before an exit(), but the reality shows, that it is quite easy to run into a situation where this is just not given; and in such a situation you don't need to care much about it. And yes, defensive programming is a must today, but while doing so you should have the feeling, that the advantages you gain are bigger then the costs you pay.

primo 06-27-2006 03:58 AM

Quote:

Originally Posted by Flesym
Your brace-if was a good example for this. But the brace-function-call to avoid bad macros.... First I don't use a macro unless I don't know what it does and second I never (in almost 15 years of programming experience) came across such a macro that would make i possible to put it between braces (at least I don't remember). -Surely everyone can construct such one, but fact is, that they must be very, very rare in the real world and putting every function call between braces is definitely not worth the effort - maybe it's defensive but it's no good style!

Oh my... I wasn't talking about putting braces around every function call. I put braces around if's and else's when there's a function call. Braces are never curly. The way you indent them may be.

Quote:

My conclusions of this:
Yes I agree, that a program flow should be clear designed and it is desirable to be able to free memory before an exit(), but the reality shows, that it is quite easy to run into a situation where this is just not given; and in such a situation you don't need to care much about it. And yes, defensive programming is a must today, but while doing so you should have the feeling, that the advantages you gain are bigger then the costs you pay.
Toy programs aren't supposed to waste your time. But in other projects that may be later extended, the time you think you saved you will lose twice. It's neither good style nor proper design to leave it to the OS. I guess I'm wasting my time stating the obvious.


All times are GMT -5. The time now is 06:44 PM.