1

Windows and Linux.

When I allocate memory in my C program, good coding wants me to free the memory before the end of my program.

Assume the following:

int main (int argc, char *argv[]) {
    char *f_name;
    FILE *i_file;

    f_name = malloc(some_amount);
    // put something in f_name */
    i_file = fopen(f_name, "r");
    if (i_file == NULL) {
        perror("Error opening file.");
        exit(EXIT_FAILURE);
    }
    free(f_name);
    return EXIT_SUCCESS;
}

If the program terminates before I call "free", will the OS recover any un-freed memory when the program exits? Or will I just nibble away from my 3Gb or so available memory until a system restart?

Thanks, Mark.

Cool Javelin
  • 776
  • 2
  • 10
  • 26

4 Answers4

3

You don't have to worry about it on popular OSes like Windows and Linux.

Virtual memory ceases to exist when the process terminates. So it's not possible for it to leak after a process terminates.

Physical memory always belongs to the OS to allocate as it pleases, whether or not your process is still running. (Unless you lock your allocations, in which case it ceases to be locked when the corresponding virtual memory mapping is destroyed which happens on process termination anyway.)

There are a few resources that are not cleaned up (like some types of shared memory) but that's pretty exotic.

When you call malloc, typically just backing store (essentially RAM+swap) is reserved and a virtual memory mapping (which is essentially free) is created. When you first write to that virtual memory mapping, physical pages of memory (RAM) are mapped into it to "back" it. That RAM always belongs to the OS to use as it pleases and the OS will re-use the RAM for other purposes if it deems that wise.

When a process terminates, its address space ceases to exist. That means any virtual memory mappings or reservations go away. Unshared physical pages will have their use count drop to zero when the virtual memory mapping goes away, rendering those pages of physical memory free.

It's worth understanding this in detail because you can easily draw the wrong conclusions about edge cases if you don't understand what's going on under the hood. Also, this will give you a framework to plug concepts such as file mappings, memory overcommit, and shared memory into.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
0

The memory is reclaimed by the OS.

Some programs (like webservers) are never meant to exit, they just keep running and serving requests. Memory they allocate technically doesn't need to be returned.

Nikola
  • 817
  • 13
  • 19
  • See my comment to silentboy's answer. This kind of answer can be very confusing and leads to misunderstandings. What does "the memory" mean? Physical memory? Backed memory? Virtual memory? – David Schwartz Mar 03 '17 at 02:29
  • Fair point, but I assumed it was pretty clear he meant `malloc`ed memory since his example contains it. – Nikola Mar 03 '17 at 02:30
  • It's really not clear what that means though since on those platforms, `malloc` just reserves address space and backing store. Someone wouldn't ask this kind of question if they already understood what a virtual address space is and that a process' virtual address space ceases to exist when they terminate. – David Schwartz Mar 03 '17 at 02:32
0

In your example, taking this branch would indeed cause memory to leak:

f_name = malloc(some_amount);
// put something in f_name */
i_file = fopen(f_name, "r");
if (i_file == NULL) {
    perror("Error opening file.");
    exit(EXIT_FAILURE);            // <--- f_name leaks here!
}

It's just a once-off leak which doesn't recur frequently throughout the life of the program and common OSes will clean up leaked memory upon termination. It'd be unlikely to be a problem impacting upon system-wide performance, however it would be a diagnostic highlighted by instruments such as Valgrind and so it'd be wise for debugging purposes to free(f_name); before you exit(EXIT_FAILURE); in that instance.

That termination isn't considered abnormal, as it's caused by a call to exit. Nonetheless, an abnormal termination caused by a call to abort or a signal being raised is likely to compound on top of this leak.

will the OS recover any un-freed memory when the program exits?

There's no requirement within the C standard that an OS exist, let alone that it recover un-freed memory. It's possible that some minimalist OSes might not clean up after you. Similarly, if your program runs within a scripting environment (i.e. CGI), or it's etched into a chip (in which case you probably wouldn't want your program terminating), then you might have issues later on.

autistic
  • 1
  • 3
  • 35
  • 80
-3

Indeed a program's memory allocations are freed automatically when the process terminates. However, in the case of a function call who receives an exception before a free() or delete call within that function's code block, the memory will not be freed unless it is referenced by a smart pointer or object of some sort. One recommended option to have allocated memory freed automatically is to use std::shared_ptr, as follows:

void BadFunction(){
    char *someMemory = (char *)malloc(1024);
    DoSomethingThatMakesAnException();
    delete someMemory;// This never gets called!
}

void GoodFunction(){
    std::shared_ptr<char> someMemory = std::shared_ptr<char>((char *)malloc(1024));
    DoSomethingThatMakesAnException();
    // someMemory is freed automatically, even on exception!
}
Michael
  • 2,268
  • 20
  • 24
  • 1
    You... you do realise this is a C-tagged question... right?! – autistic Mar 03 '17 at 02:54
  • 1
    You should: 1. [never cast `malloc` (or to/from a `void *` anywhere else) in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)... 2. [never use `malloc` (and certainly don't use `delete` to clean up `malloc`d objects) in C++](http://stackoverflow.com/questions/184537/in-what-cases-do-i-use-malloc-vs-new)... 3. choose a language: C or C++... In this question, C is tagged, yet in your answer, (invalid) C++ is encouraged. – autistic Mar 03 '17 at 02:58
  • Fortunately, C doesn't have exceptions, so this scenario is irrelevant. – Lundin Mar 03 '17 at 07:58
  • @Seb -- So you are saying that a mix of C and C++ is "invalid" C++? This is a stylistic assertion, not one of functionality. The code I provided would work just fine, whether you like it or not. And yes, "delete" works with malloc() allocations. While it is true that I assumed C++ support in this code, calling it invalid because it does not match your programming style is just plain silly. This is like saying that using Windows is "invalid" because you prefer Linux. – Michael Mar 03 '17 at 13:59
  • Are you quoting the word "invalid" because you don't understand its definition? Let us start with that, as both C and C++ are defined by legal documents we could use this definition: "(especially of an official document or procedure) not legally recognized because it contravenes a regulation or law." [Mixing `malloc` and `delete`, for example, results in undefined behaviour (invalid C++)](http://stackoverflow.com/questions/10854210/behaviour-of-malloc-with-delete-in-c). You should probably learn both languages by the standards before you attempt to argue about them. – autistic Mar 05 '17 at 04:14
  • Furthermore, mixing C and C++ is invalid because you can't prove that it works 100% of the time and because I can prove that it *doesn't* work *some* of the time. Proof: `char *foo = malloc(42); // works in C, not in C++`. Whether you like it or not, your mixture of C and C++ contravenes one law or another; in this case, your C++ code doesn't compile using a C compiler, which makes it irrelevant for this question (hence the downvotes, none of which were mine up until now). – autistic Mar 05 '17 at 04:17
  • If you intend to argue that a common subset of C and C++ is appropriate for compatibility, you're restricting yourself to *the worst* of both languages when with *much* less effort you could keep your (slightly nicer) C code separate from your (much nicer) C++ code and link them together using the linker once they've been translated to a common language (object code). – autistic Mar 05 '17 at 04:25
  • Words often have multiple definitions in common language, and *invalid* is definitely one of them. We are using different definitions here. The validity I am using relates to whether something works in the real world while you are using a rules-based approach. Different strokes for different folks. – Michael Mar 05 '17 at 04:41