Note that there are some explanatory texts on larger screens.

plurals
  1. POFreeing memory in a function
    primarykey
    data
    text
    <p>I'm writing a simple program in C that finds anagrams of words based on looking them up in a hash table. What I have is an array of hash tables, where words are indexed by their length and hashed within by the summation of their letters, e.g. a = 1, b = 2, etc. </p> <p>I'm still getting acquainted with dynamic memory management in C, so this question may be quite simple, but I have a functions that allocate and deallocate memory for each hash table (and its inside data). </p> <p>I originally wrote this program using a single hash table and after running the program through valgrind I found that the memory had been freed correctly and there were no leaks. However, when expanding the program to use an array of hash tables, valgrind began to find possible leaks (though it's reporting them as still reachable). I'm confused as to why the memory isn't being freed correctly in the array of hash tables, although each hash table in the array is being run through the deallocate function that was used originally. </p> <p>Gist with the full code <a href="https://gist.github.com/4559692" rel="nofollow">Full Code</a></p> <pre><code>typedef struct Bucket Bucket; typedef struct HashTable HashTable; struct Bucket { char* data; Bucket *next; }; struct HashTable { int size; Bucket **buckets; }; int main(int argc, char const *argv[]) { // Allocate memory for array of hash tables HashTable** hash_array = (HashTable**) malloc(sizeof(HashTable*) * WORD_SIZE); for(i = 0; i &lt; WORD_SIZE; i++) { hash_alloc(&amp;hash_array[i], BUCKET_COUNT); } // Main logic here... // Free memory for(i = 0; i &lt; WORD_SIZE; i++) { hash_dealloc(hash_array[i]); } free(hash_array); return 0; } </code></pre> <p>Hash Table Allocation function</p> <pre><code>void hash_alloc(HashTable** a, unsigned int size) { *a = (HashTable*) malloc(sizeof(HashTable)); (*a)-&gt;buckets = (Bucket**) malloc(sizeof(Bucket*) * size); (*a)-&gt;size = size; } </code></pre> <p>Hash Table Deallocation function</p> <pre><code>void hash_dealloc(HashTable* a) { int i; Bucket* current, *temp; for(i = 0; i &lt; a-&gt;size; i++) { current = a-&gt;buckets[i]; while(current != NULL) { temp = current; free(temp-&gt;data); current = current-&gt;next; free(temp); } free(current); } free(a-&gt;buckets); free(a); } </code></pre> <p>Add to hash table function</p> <pre><code>void add_to_hash_array(HashTable** a, char* data) { // Removed some other logic for readability... replace_str(data, "\n", "\0"); newNode-&gt;data = strdup(data); newNode-&gt;next = currentTable-&gt;buckets[index]; currentTable-&gt;buckets[index] = newNode; } else { return; } } </code></pre> <p>Valgrind output </p> <pre><code>==39817== 261,120 bytes in 128 blocks are still reachable in loss record 5 of 7 ==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==39817== by 0x400A38: hash_alloc (main.c:73) ==39817== by 0x4008B0: main (main.c:39) ==39817== ==39817== 286,936 bytes in 31,553 blocks are still reachable in loss record 6 of 7 ==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==39817== by 0x4EBAD71: strdup (strdup.c:43) ==39817== by 0x400D4D: add_to_hash_array (main.c:141) ==39817== by 0x400914: main (main.c:51) ==39817== ==39817== 504,848 bytes in 31,553 blocks are still reachable in loss record 7 of 7 ==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==39817== by 0x400D16: add_to_hash_array (main.c:136) ==39817== by 0x400914: main (main.c:51) </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload