3

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,

ant2009
  • 27,094
  • 154
  • 411
  • 609
  • Can you post the smallest *complete* program about which valgrind still complains in this manner. – NPE Dec 16 '10 at 16:20
  • There is something going on somewhere else in my source code. Just posted an comment to Pax below. – ant2009 Dec 16 '10 at 16:33

4 Answers4

4

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
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I just just switch my project to another branch. I took out all the unrelated code and only the source code where I am actually allocating memory. So the code looks like what I have posted. The memory was freed. So I think there is something going on somewhere else. I will need to investigate further. However, what is the best technique to find memory errors? – ant2009 Dec 16 '10 at 16:32
  • Thanks for the information. I will check my source code and report back with any new information. Thanks. – ant2009 Dec 16 '10 at 16:52
2

There is no obvious error in your allocations/frees.

It looks like the content of result has been changed somehow (overwritten by some wild pointer ?).

One easy way to check that is to print memory address values of pointer (using printf("%p", ...)) immediately after the allocation using strdup and just before freeing. If it changed : bingo!

Do it also with result, another explanation could be that the pointer to result has changed (and henceforth the values pointed to).

Now, if the pointer has indeed changed how to pinpoint where it occurs ?

One solution can be to run the program using a debugger. This can be very time consuming in some case, but it usually works. But if this is not an option, there is another way. I usually find it faster than using a debugger.

Keep a copy of the allocated pointer in another variable, preferably make it remote from the memory chunk where is your corrupted pointer (a global will usually do).

Now in the control flow put assertions like:

assert(result == saved_result);

At some place the assertion should fail and you will eventually find the problem.

Aftwerward, you should not forget to remove your assertions that should not be left in the final project. To be sure of that just remove the saved_result variable. The program won't compile in debug mode if any assertion is left.

kriss
  • 23,497
  • 17
  • 97
  • 116
2

You can also debug your application with gdb and watch if any pointer gets changed with the "watch" command. Place a breakpoint on your main function and do a step by step followup to discover where the problem resides.

Regards,

Miguel

Miguel Rentes
  • 994
  • 1
  • 10
  • 27
1

"72 bytes in 6 blocks", doesn't sound like "Steve Martin" or "Jack Jones". You're not overwriting the pointers at some point(!)?

onemasse
  • 6,514
  • 8
  • 32
  • 37