Thread: Freeing memory before exit

  1. #1
    Registered User
    Join Date
    Dec 2005
    Posts
    32

    Freeing memory before exit

    I'm writing a small program which reads a single line of input, mallocs a bunch of structs, calculates and prints results and then exits. Should I free any mallocs just before the program exits (as early as possible), or does it matter? I guess it's crappy practice if I don't... But my structs are stored as a binary tree, and I have to traverse the entire tree to remove them. It just seems like more of a hassle than I need.

    Thanks!
    -tretton

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    So in short, "Should I be a lazy programmer, or do what I already know I should do?" Wow, that's a tough call.

    There's nothing in the language that says what you don't free will be returned to the OS correctly when your program exits.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    *boggle* That's got to be the stupidest read I've ever seen.
    On the other hand, there are programs (such as interpreters) that don't know what memory they're done with (i.e. what memory could be freed) until it's time to exit, and since all memory should be released at exit, it would be a needless, potentially expensive, and error-prone exercise for the program to explicitly free all of it.
    ........it, I'm never calling free again. I mean, what's the point, right? *boggle*


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Dec 2005
    Posts
    32
    Yes, I know it's lazy, but:

    [...] if a program has lots of complicated, interconnected, dynamically-allocated memory structures, and if the program is about to exit, going to great lengths to free all the memory might add nothing more to the program beyond a bigger code-space footprint, a slightly longer running time, and a higher probability of bugs.
    (Quote from: http://c-faq.com/malloc/freeb4exit2.html)

    And this is pretty much my case (maybe not overly complicated, but interconnected). I know I'm arguing about something fundamentally obvious, but what would you guys do? (I think I know what you would do, quzah. ) I'm freeing most of my structs as soon as I can, but a few of them are locked in chained returns and cannot be disposed of until the very end of main(). And even then, trying to free them would probably require a redesign of some of my functions.

    (I'm going to post a link to the source code when it's finished, but some things aren't really behaving yet.)

    Anyway, thanks for your replies!
    -tretton

  6. #6
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    I can't help but think of how easy this would be with OOP and Destructors. Personally, and I don't have much experience at this level of programming, but I'd probably agree with the article. If free() is really that volatile and unreliable, then it may be better of to let the program close and let the OS deal with retrieving all the memory.
    Sent from my iPadŽ

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    If you can't free what you've allocated because it's too "complicated", then you need to redesign, IMO. I can't picture a scenario where I write something where I'm not able to free something I allocate because it's too convoluted.

    Ok, I CAN picture a scenario, but it would have to involve alcohol.


    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    Dec 2005
    Posts
    32
    Wee, I admit defeat! Redesigning the function was of course trivial after a good night's sleep, and I basically went from:

    Code:
    return create_exp(main_conn->conn, '\0', build_tree(start, main_conn->start), build_tree(main_conn->stop, stop));
    /* When doing this, I lost track of main_conn. */
    to:

    Code:
    node = create_exp(main_conn->conn, '\0', build_tree(start, main_conn->start), build_tree(main_conn->stop, stop));
    free(main_conn);
    return node;
    Now I can free everything without further ado. Haha, pretty obvious when I look at it now.

    By the way, when a function returns, is every locally created variable free()'ed, technically speaking? I mean, I know that they exist only within the function, but is free() equivalent to that auto-destruction?

    (I'm sorry about all these stupid questions, but I'm learning C by myself and don't really have anyone to ask. The fact that my C book isn't very in-depth doesn't help. So until I get my next book, please bear with me. )

    -tretton
    Last edited by tretton; 02-01-2006 at 10:31 AM.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > By the way, when a function returns, is every locally created variable free()'ed, technically speaking?
    The rule is (in it's strictest form) is that if you called malloc, then you must call free.

    If (and only if), you're going to call free, then exit the program anyway, then you should be able to get away without calling free. But if you're planning to make a library out of your program for example, then calling free is a good idea just to be nice and tidy.

    It also means your code will pass various leak detectors without you having to worry about whether its a real leak, or just merely a block which lasts until the end of the program.

  10. #10
    Registered User
    Join Date
    Dec 2005
    Posts
    32
    True that. Now I'm freeing everything.

    I should have been more specific with that last question though, sorry about that. I meant all variables declared in the beginning of the function (int x, char *p, etc.), not any stuff I malloc myself. It's only a small detail, I guess, but I want to know if the memory associated with those variables is deallocated in the same way as free deallocates, i.e. not really returning the memory to the OS, but to the own program.

    I read through the malloc section of c-faq, and I'm beginning to understand my memory management now.

    -tretton

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Local variables are a whole different set of variables, which are managed by the compiler.
    Usually, they're stored on the stack whereas malloc/free use a memory pool.

  12. #12
    ---
    Join Date
    May 2004
    Posts
    1,379
    One of my instructors once told me off for calling free what a dick head

  13. #13
    Sr. Software Engineer filker0's Avatar
    Join Date
    Sep 2005
    Location
    West Virginia
    Posts
    235
    Quote Originally Posted by tretton
    Code:
    node = create_exp(main_conn->conn, '\0',
                                   build_tree(start, main_conn->start), 
                                   build_tree(main_conn->stop, stop));
    free(main_conn);
    return node;
    Now I can free everything without further ado. Haha, pretty obvious when I look at it now.
    Um... Unless create_exp() somehow frees anything pointed to by main_conn, simply calling free() on main_conn will not free everything that you've allocated that is pointed to by pointers within main_conn. It will only free the single allocation in which main_conn was allocated.

    On most operating systems, calls to malloc/calloc/realloc deal with a pool of memory, referred to as the "pool" or the "heap". The heap is not shared between different processes. When a program uses malloc() or one of its siblings, the library code checks the chain of free memory within the pool that it manages, and if it can't find one of the desired size, it makes a request to the operating system (sbrk() on 7th edition Unix) to add a chunk to the pool (this may be contiguous with the existing pool or disjoint, depending on runtime environment). The operating system tracks the allocations made for the process. When a program calls free(), the allocated chunk of memory that is pointed to is linked back into the free pool. (Coelescing of adjacent free blocks is often done by the malloc() code when trying to find a free chunk in the pool large enough to satisfy a request.) The memory allocated by the OS to this pool is not always returned to the OS (depends on how it's allocated to the process in the first place) until the process terminates, at which point all of the allocations made for the malloc pool are reclaimed by the system.

    Different operating systems offer other types of allocation, but usually they use a different API (different library calls) than the standard malloc/calloc/realloc/free pool management. In these cases, allocations made through these different APIs may or may not be reclaimed automatically by the system on process exit.

    You should always know how to delete your trees.

    You should (I'd like to say "must") always free any resources that you don't know for sure are automatically reclaimed by the system on program exit.

    As far as memory allocated by malloc() or its siblings, I'll leave it up to you whether you choose to spend the time pruning the tree until you've chopped it off at the root or not. I do, but that's me.

    There are languages and techniques that make all of this automatic, but C is not one of those languages.
    Insert obnoxious but pithy remark here

  14. #14
    Sys.os_type="Unix";;
    Join Date
    Aug 2005
    Posts
    52
    The bottom line being...
    While most of the popular operating systems will automatically reclaim the memory your program has allocated for itself, it's not a requirement of the operating system and not all operating systems do it. So unless you're not looking for portability including potential memory leaks, free()ing the memory is always a good thing to do.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problems with shared memory shmdt() shmctl()
    By Jcarroll in forum C Programming
    Replies: 1
    Last Post: 03-17-2009, 10:48 PM
  2. Issues with pointer and freeing its associated memory
    By tytelizgal in forum C Programming
    Replies: 10
    Last Post: 10-17-2008, 03:00 PM
  3. Calling exit() with dynamic memory
    By miclus in forum C Programming
    Replies: 11
    Last Post: 10-05-2004, 11:49 AM
  4. memory allocation and freeing
    By Jase in forum Linux Programming
    Replies: 1
    Last Post: 05-25-2003, 06:26 AM
  5. freeing memory
    By mart_man00 in forum C Programming
    Replies: 1
    Last Post: 04-27-2003, 08:51 PM