Cannot free memory after using strdup

ant2009 picture ant2009 · Dec 16, 2010 · Viewed 8.5k times · Source

gcc 4.5.1 c89

I am trying to free some memory. However, when I check with valgrind the memory hasn't been freed. I am wondering what I am doing wrong.

I have the following structure:

typedef struct tag_cand_results {
    char *candidate_winners[NUMBER_OF_CANDIDATES];
} cand_results;

I create an object of this structure:

cand_results *results = NULL;

I allocate some memory for the structure.

results = calloc(1, sizeof *results);

Assign some data to it

results->candidate_winners[0] = strdup("Steve Martin");
results->candidate_winners[1] = strdup("Jack Jones");

Then I try to free all the memory allocated:

free(results->candidate_winners[0]);
free(results->candidate_winners[1]);
free(results);

Just to be safe assign to NULL
results = NULL;

I get the following output from valgrind.

==8119== 72 bytes in 6 blocks are definitely lost in loss record 1 of 2
==8119==    at 0x4A05E46: malloc (vg_replace_malloc.c:195)
==8119==    by 0x3FE2E82A91: strdup (strdup.c:43)
==8119==    by 0x400E5A: main (driver.c:116)
==8119== 
==8119== 72 bytes in 6 blocks are definitely lost in loss record 2 of 2
==8119==    at 0x4A05E46: malloc (vg_replace_malloc.c:195)
==8119==    by 0x3FE2E82A91: strdup (strdup.c:43)
==8119==    by 0x400E72: main (driver.c:117)

I don't know why the memory is not been freed?

Many thanks for any suggestions,

Answer

paxdiablo picture paxdiablo · Dec 16, 2010

If that is actually the sequence of events, then valgrind is wrong. The memory is being freed.


As to the best technique requested in your comment, normally I would say valgrind but perhaps not in this case :-)

Some things to check.

  • What happens if you just call malloc(30) instead of strdup(some_string) (in both cases)?
  • Remove the (malloc-or-strdup)/free pairs one at a time to see what happens.
  • I haven't seen your actual code so put a printf before and after every strdup and free line to make sure they're all being run.
  • Post a full small program here (that exhibits the problem) so we can check it out.

For what it's worth, the following small (complete) program:

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

#define NUMBER_OF_CANDIDATES 10
typedef struct tag_cand_results {
    char *candidate_winners[NUMBER_OF_CANDIDATES];
} cand_results;

int main (void) {
    cand_results *results = NULL;

    results = calloc(1, sizeof *results);

    results->candidate_winners[0] = strdup("Steve Martin");
    results->candidate_winners[1] = strdup("Jack Jones");

    free(results->candidate_winners[0]);
    free(results->candidate_winners[1]);
    free(results);

    results = NULL;

    return 0;
}

results in the following valgrind output:

==9649== Memcheck, a memory error detector
==9649== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==9649== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for
         copyright info
==9649== Command: ./qq
==9649== 
==9649== 
==9649== HEAP SUMMARY:
==9649==     in use at exit: 0 bytes in 0 blocks
==9649==   total heap usage: 3 allocs, 3 frees, 64 bytes allocated
==9649== 
==9649== All heap blocks were freed -- no leaks are possible
==9649== 
==9649== For counts of detected and suppressed errors, rerun with: -v
==9649== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8)

In other words, no problems. So it may be something else in your case (an environment issue perhaps). This particular run was done on Ubuntu Lucid (10.04), gcc 4.4.3, c89 mode.

I'd suggest typing in that code exactly on your system to see what happens. The command line I used to compile and test was:

gcc -std=c89 -o qq qq.c
valgrind ./qq