ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195
Rep:
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?
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.
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.
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! ;-)
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.
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195
Rep:
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.
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.
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.
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.