180 likes | 201 Views
Learn how to effectively free dynamically allocated memory, prevent memory leaks, and avoid program errors. Understand implicit and explicit memory allocation and identify memory leak sources. Use Valgrind to detect memory leaks.
E N D
CSc 352Freeing Dynamically Allocated Memory Saumya Debray Dept. of Computer Science The University of Arizona, Tucson debray@cs.arizona.edu
Motivation • Dynamically allocated memory should be freed when no longer needed • The C runtime system does not automatically reclaim memory • memory leaks increase the program’s memory footprint • this can lead to slow performance, program crashes • This needs to be done with care: • too-aggressive freeing can lead to program errors • too-passive freeing can miss memory allocated “behind the scenes”, e.g., through strdup().
Issues • Understanding when dynamic memory allocation happens • explicit (by the programmer) • implicit (by library routines) • Through the course of the program: • identifying when memory is no longer needed • being aware of multiple pointers to a block of memory • Identifying and fixing memory leaks
Understanding dynamic memory allocation • Dynamic allocation can be explicit or implicit • explicit: when the programmer invokes malloc, calloc, etc. • implicit: when the memory allocation happens “behind the scenes” in a library routine • getline • strdup • GNU extension to scanf • fopen • … In general, if memory appears “by magic” at runtime, chances are it’s being allocated implicitly.
Freeing up memory • Use free(p) when a memory block is no longer needed • p is a pointer to a block of memory previously allocated through malloc or calloc • Pitfalls: • accessing a previously-freed block is an error • freeing a block of memory twice is an error pointer malloc’d memory block watch out for multiple ways to reach a memory block
Freeing up memory • General approach: • free up memory “hanging off” a block of memory • grab any pointers you need to traverse the rest of the data structure • then free the block itself 1 deallocate memory “hanging off” this node 2 grab this pointer 3 free this block
Finding memory leaks 1 use valgrind to determine whether the program has memory leaks
Finding memory leaks 2 indicates where the lost memory was allocated
Finding memory leaks 2 forgot to fclose() after reading the file!
After fclose-ing the input stream less leakage than before, but still quite a bit need to free the linked list of states
Freeing up a linked list 1 naïve code to free the nodes in a linked list
Freeing up a linked list 2 stateList st0 st1
Freeing up a linked list 3 • no memory errors • less memory being leaked • but some leakage persists! • reason: structures “hanging off” states not being freed // a DFA state typedefstruct vertex { char *name; struct edge *transitions; boolisFinal; struct vertex *next; } state; // a transition between states typedefstruct edge { char ch; struct vertex *from, *to; struct edge *next; } edge;
Freeing up a linked list 4 Solution: free up the edges “hanging off” each state before freeing hat state
Freeing up a linked list 4 a lot better! but some leakage still left!
Freeing up a linked list 4 // a DFA state typedefstruct vertex { char *name; struct edge *transitions; boolisFinal; struct vertex *next; } state;
Summary • Should free up dynamically allocated memory when done • Use valgrind to identify memory leak sources! • Needs to be done carefully • freeing up “live” memory will result in program errors • Pay attention to implicitly-allocated memory, e.g.: • file pointers • strings allocated through strdup() • when freeing up a struct, first free up any unused memory “hanging off” the struct