70

Let's consider a fictional program that builds a linked list in the heap, and at the end of the program there is a loop that frees all the nodes, and then exits. For this case let's say the linked list is just 500K of memory, and no special space managing is required.

  • Is that a waste of time, because the OS will do that anyway?
  • Will there be a different behavior later?
  • Is that different according to the OS version?

I'm mainly interested in UNIX based systems, but any information will be appreciated. I had today my first lesson in OS course and I'm wondering about that now.

Edit: Since a lot of people here are concerned about side effects, and general 'good programming practice' and so. You are right! I agree 100% with your statements. But my question is only hypothetical, I want to know how the OS manages this. So please leave out things like 'finding other bugs when freeing all memory'.

Ramzi Kahil
  • 1,089

16 Answers16

70

My main problem with your approach is that a leak detection tool (like Valgrind) will report it and you will start ignoring it. Then, some day a real leak may show up, and you'll never notice it because of all the noise.

42

Once I had to implement an algorithm using deques which were allocated dynamically. I was also wondering whether I needed to deallocate all the allocated data at exit.

I decided to implement the deallocation anyway and found out that the program crashed during deallocation. By analysing the crash, I found an error in the implementation of the main data structure and algorithms (a memory leak).

The lessons I learnt were:

  1. Always implement deallocation for the data you allocate, this makes it more reusable in case you want to embed your code in a larger system.
  2. Deallocation can serve as an additional check that your allocated data is in a consistent state when it is released.

Just my 2 cents.

EDIT

Small clarification: Of course all memory allocated to a process gets released when the process is terminated, so if the only requirement is to release the allocated memory, doing it explicitly is indeed a waste of time.

Giorgio
  • 19,764
19

OK, I just got an Email back from my instructor, with a very good and reasonable answer. Here it is:

Hi Ramzi,

Thanks for the link to the interesting messages thread which you started.

As per our discussion, malloc operates on the process' virtual memory. So, when the process dies, its virtual address space "disappears", and any physical memory mapped to it is freed. Hence, disregarding "good software engineering practices" and such, dynamic memory de-allocation just before exiting a process is indeed a waste of time.

(Needless to say, this is not the case when a single thread terminates but other threads of that process keep executing.)

So according to this:

  • It is a waste of time
  • Will have no later affects
  • Is independent of OS versions.
Ramzi Kahil
  • 1,089
14

Always free your resources. Freeing all your resources is important because it's the only way of being able to effectively detect leaks. For the project I'm working on I've even got wrappers around malloc/realloc/free to insert canaries, track statistics, etc; simply to detect problems sooner.

However, except for leak detection, for resources that are freed at exit (not before) it is a waste of time. The OS must be able to free it (e.g. in case the process crashes, or even just freeing RAM used for the process' code); and the OS should be able to free it faster than you can from user-space because the kernel will do "wholesale" rather than "piecemeal", and there's less transitions between kernel and process involved.

Fortunately you don't have to choose one way or another. If you want to make sure your code is correct (and you do), but you also want the best possible performance, then do something like:

#ifndef FAST_EXIT
    free(stuff);
#endif
Brendan
  • 4,005
8

The cleanup routine may be useful if you do it periodically to regain space, or to prove that you are able to reclaim exactly as many nodes as you allocated, to verify that there are no memory leaks. But as housekeeping immediately before the process dies, it makes no sense, since the OS regains control of that entire arena of memory at that instant.

Kilian Foth
  • 110,899
4

Will there be a different behavior later?

There is a critical question related to this one that you need to ask:

Will anyone ever use this code ever again for any reason?

If the answer could ever be yes, whether the code is used alone or as a part of a larger system, you have created a monumental memory leaking landmine for the next person to step on.

It is very hard to remember during your coursework that you are learning how to make software that other people are going to use including future-you (rather than just solving the homework problem of the day). This means that you need to abide by certain basic programming behaviors including: give back the resources when you are done with them.

Bob Cross
  • 539
2

If you implement your own data type "linked list" not writing a cleanup routine/deconstructor will give you more headaches in the long run than you might think.

Without cleanup code reusing what you wrote will be much harder since your type cannot be used without taking special care (e.g. never create them in a function or loop, but preferably exclusively in main).

Do yourself and everybody else a favor and just write you list_cleanup or ~List.

1

On multi-user systems, the OS will always free such resources because it would be a security risk if it didn't. Your memory contents might end in someone else's process!

MSalters
  • 9,038
1

Cleanup routines can have bugs just like any other code. A sad sight is a program that does what you want except that it hangs or crashes at exit. General practice is to have code clean up after itself, but memory cleanup at process exit is a case where you don't have to.

Sonia
  • 231
  • 1
  • 3
1

Almost always yes. Free shared-memory semaphores and UDP server resources (the OS doesn't know how to notify connected UDP servers that you're done).

Joshua
  • 1,674
1

I always clean up resources on normal exit. It's a safety check that my resource allocation/deallocation calls are done right. This check has alerted me to hidden bugs on more than one occasion. It's like balancing the books of a business at the end of the day.

There may be edge cases such as @MSalter described in his comment, but even that would generally start me looking at customized memory management, rather than just letting the OS clean up and hoping for the best.

0

If you are 100% sure not other process is referencing you linked list and the nodes therein, OK.

100% is a pretty high number, though. Was your list referenced by some persistence code that's being pooled? Does a UI component still have a handle on it? Anything else?

Memory leaks generally don't happen on purpose.

Matthew Flynn
  • 13,495
  • 2
  • 39
  • 58
0

The problem is that today it's a linked-list node, and tomorrow, it's a resource the OS can't clean up by itself. Is it fast and safe to leave the OS to clean up heap memory? Yes. But does that make it a good idea? Not necessarily.

DeadMG
  • 36,914
-1

Some C++ GUI libraries leak resources like this. This is not a value judgement, but leaking resources and letting the OS reclaim them is a somewhat common occurrence in "real code."

It's always good practice to clean up though, you never know when you'll want to integrate that tool with something else, and then the work is already done (instead of going into the wayback/ remembering machine and remembering all the spots you intentionally leaked).

In one case we actually found a bug because the deallocation was causing a crash because some other memory bug had overwritten the header that delete uses. So, sometimes it can actually help you to find bugs in other areas to free all your resources (you can find an overrun in the previous block).

anon
  • 1,494
-1

One thing to think about:

If your code is in a DLL, then you should clean up for sure otherwise if you assume that your process exit will free the resources then your DLL will not be reloadable.

sylvanaar
  • 2,305
-2

Managing memory is the best-practice while taking decision to release it in a context is optimization!

Now the ball is in our court!

sarat
  • 1,121