3

I understand that if you're allocating memory to store something temporarily, say in response to a user action, and by the time the code gets to that point again you don't need the memory anymore, you should free the memory so it doesn't cause a leak. In case that wasn't clear, here's an example of when I know it's important to free memory:

#include <stdio.h>
#include <stdlib.h>

void countToNumber(int n)
{
    int *numbers = malloc(sizeof(int) * n);

    int i;
    for (i=0; i<n; i++) {
        numbers[i] = i+1;
    }
    for (i=0; i<n; i++) {
        // Yes, simply using "i+1" instead of "numbers[i]" in the printf would make the array unnecessary.
        // But the point of the example is using malloc/free, so pretend it makes sense to use one here.
        printf("%d ", numbers[i]);
    }
    putchar('\n');

    free(numbers); // Freeing is absolutely necessary here; this function could be called any number of times.
}

int main(int argc, char *argv[])
{
    puts("Enter a number to count to that number.");
    puts("Entering zero or a negative number will quit the program.");

    int n;
    while (scanf("%d", &n), n > 0) {
        countToNumber(n);
    }

    return 0;
}

Sometimes, however, I'll need that memory for the whole time the program is running, and even if I end up allocating more for the same purpose, the data stored in the previously-allocated memory is still being used. So the only time I'd end up needing to free the memory is just before the program exits.

But if I don't end up freeing the memory, would that really cause a memory leak? I'd think the operating system would reclaim the memory as soon as the process exits. And even if it doesn't cause a memory leak, is there another reason it's important to free the memory, provided this isn't C++ and there isn't a destructor that needs to be called?

For example, is there any need for the free call in the below example?

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    void *ptr = malloc(1024);
    // do something with ptr
    free(ptr);
    return 0;
}

In that case the free isn't really inconvenient, but in cases where I'm dynamically allocating memory for structures that contain pointers to other dynamically-allocated data, it would be nice to know I don't need to set up a loop to do it. Especially if the pointer in the struct is to an object with the same struct, and I'd need to recursively delete them.

flarn2006
  • 1,787
  • 15
  • 37
  • 2
    yes, because your program will change over time and you will forget about this hack – amdixon Oct 06 '15 at 09:19
  • Please refer http://stackoverflow.com/questions/654754/what-really-happens-when-you-dont-free-after-malloc – hazzelnuttie Oct 06 '15 at 09:24
  • 1
    Proper resource ownership discipline is part of *understanding* how to build a system. Your question may as well be "do I really need to understand what I'm doing if it's just something simple". – Kerrek SB Oct 06 '15 at 09:27
  • 1
    The main issue is, immediately after you've written code that does dynamic allocations, you should write the clean up code. Otherwise, you'll end up writing programs with memory leaks in cases where the manner of clean up does matter. `free()` can never cause any harm. – Lundin Oct 06 '15 at 10:01

1 Answers1

6

Generally, the OS will reclaim the memory, so no, you don't have to free() it. But it is really good practice to do it, and in some cases it may actually make a difference. Couple of examples:

  • You execute your program as a subprocess of another process. Depending on how that is done (see comments below), the memory won't be freed until the parent finishes. If the parent never finishes, that's a permanent leak.
  • You change your program to do something else. Now you need to hunt down every exit path and free everything, and you'll likely forget some.
  • Reclaiming the memory is of OS' volition. All major ones do it, but if you port your program to another system it may not.
  • Static analysis and debug tools work better with correct code.
  • If the memory is shared between processes, it may only be freed after all processes terminate, or possibly not even then.

By the way, this is just about memory. Freeing other resources, such as closing a file (fclose()) is much more important, as some OSes (Windows) don't properly flush the stream.

mtijanic
  • 2,872
  • 11
  • 26
  • Nice, but for the last claim: **Freeing other resources, such as closing a file (fclose()) is much more important.**, all open files are closed before program termination – David Ranieri Oct 06 '15 at 09:29
  • @AlterMann Yes, but any data written to it is not flushed. Try opening a file for write, writing a couple of bytes to it, and exiting without closing (or `fflush()`). You'll end up with an empty file. – mtijanic Oct 06 '15 at 09:30
  • 3
    @mitjanic: nops, (C99, 7.19.3p5) "If the main function returns to its original caller, or if the exit function is called, all open files are closed (hence all output streams are flushed) before program termination." – David Ranieri Oct 06 '15 at 09:32
  • 2
    @AlterMann Well, I'll be.. I still stand by my original point, seeing as at least Windows/MSVC doesn't follow the standard, and that's a pretty major platform. Still, you are completely correct. Thanks! – mtijanic Oct 06 '15 at 09:34
  • @AlterMann - And if there's an error when those output streams are flushed? Flushing a stream is the same as any other write operation - it can fail. The flushing of streams on `exit()` or returning from `main()` provides *no error checking*. – Andrew Henle Oct 06 '15 at 09:50
  • @mtijanic "The memory won't be freed until the parent finishes" - that's not true, at least on Linux. When process exits, its memory is claimed by kernel. There is some info that is retained until parent calls `wait`/`waitpid`, mainly process table entry but its unrelated to any resources acquired by program. – el.pescado - нет войне Oct 06 '15 at 09:51
  • @el.pescado Admittedly, I haven't tested any of this, so I'll edit to reflect that. And what you say does make sense for `fork()`/`clone()` and similar calls, but there are also cases when you want the entire state of the process available. For example, gdb likely spawns the process in a different manner when debugging it. Likewise, starting the program as a pthread of the parent shouldn't free anything until the parent terminates. – mtijanic Oct 06 '15 at 09:56
  • @AndrewHenle, you are right, but in my first comment I was talking about "unclosed files" (not "unflushed files"). – David Ranieri Oct 06 '15 at 10:01
  • @el.pescado - There are in fact some operating systems where it's possible to run multiple processes in the same address space, similar to multithreading in Linux. – Andrew Henle Oct 06 '15 at 10:04