[Sussex] C programming help - again!

Steve Dobson steve at dobson.org
Mon May 9 22:28:42 UTC 2005


Hi Captain

On Mon, May 09, 2005 at 11:09:20PM +0100, Captain Redbeard wrote:
> Consider the following program:
> 
> #include <stdlib.h>
> #include <stdio.h>
> 
> int main()
> {
>   struct TestStruct
>   {
>     int X;
>     int Y;
> 
>     char *CharString;
>   } *TestStructPtr;
> 
>   TestStructPtr = malloc (sizeof (struct TestStruct));
>   TestStructPtr->CharStr = malloc ((sizeof (char)) * 16);
> 
>   TestStruct->X = 3;
>   TestStruct->Y = 4;
>   TestStruct->CharString = "Hello World!\n\n\n");

Your problem lies with this line here. See below.

>   printf ("TestStructPtr = (%i, %i).\n\n", 
> TestStructPtr->X, TestStructPtr->Y);
>   printf ("CharString = %s.", TestStructPtr->CharString);
> 
>   free (TestStructPtr);
> 
>   return 0;
> }
> 
> This program contains a pointer to a struct (TestStructPtr) 
> that itself contains a pointer (CharString), nested pointers 
> if you will.
> 
> When I compile this program with the option "-Wall" included 
> I get no error or warning messages and when when run the 
> program runs as expected so all seems OK.  However when I 
> run the same program under Valgrind I get warned of a memory 
> leak.  This makes sense as the CharString pointer has not 
> been freed up.  To handle this leak I added an extra free() 
> command specifically for that pointer so the program now 
> looks like this:
> 
> .
>   printf ("TestStructPtr = (%i, %i).\n\n", 
> TestStructPtr->X, TestStructPtr->Y);
>   printf ("CharString = %s.", TestStructPtr->CharString);
> 
>   free (TestStruct->CharString);
>   free (TestStructPtr);
> .
> .
> .
> 
> 
> 
> Now the program still compiles OK but when the new line is 
> reached at run-time I get the following error message:
> 
> 
> *** glibc detected *** free(): invalid pointer: 0x080485b4 ***
> 
> 
> Obviously that doesn't work but I've no idea why.  OK, let's 
> try something else, let's create a new char pointer that 
> points to the same memory address as CharString, that way we 
> can free() CharString by proxy, as it were.  This is the 
> next version of the code:
> 
> 
> 
> .
> .
> .
>   printf ("TestStructPtr = (%i, %i).\n\n", 
> TestStructPtr->X, TestStructPtr->Y);
>   printf ("CharString = %s.", TestStructPtr->CharString);
> 
>   char *TempPtr = TestStructPtr->CharString;
> 
>   free (TempPtr);
>   free (TestStructPtr);
> .
> .
> .
> 
> 
> 
> The program still compiles OK but when I run it I get an 
> error message similar to the one above when it comes to the 
> "free (TempPtr);" line.  Why does free() not work in this 
> situation and how do I properly free nested pointers?

 The String "Hello World!\n\n\n" is allocated from non-writable
program memory.  If you were to add:

  printf("Addr of CharString: 0x%08x\n", TestStruct->CharString);

before and after the assignment you will see that the value
has changed.  What the statement does is point CharString
at the fix string, *NOT* copy the string into the memory
allocated from the heap (my malloc).

You need to use strcpy() to copy the string into the memory
allocated, or use strdup() to allocated and copy in one go.

Steve




More information about the Sussex mailing list