LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-09-2005, 05:05 PM   #1
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Rep: Reputation: 15
Correct use of free() in complex structures


Consider the following program:

Code:
#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");

  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:

Code:
.
.
.
  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:

Code:
*** 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:

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?
 
Old 05-09-2005, 06:10 PM   #2
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
The problem is not with free() but because you lose the malloc you originally gave to CharString.

malloc() returns a pointer to the address of the memory reserved. So you set CharString equal to that. That's perfectly legit.

Then you do this:
Code:
  TestStruct->CharString = "Hello World!\n\n\n");
That's where your wheels come off. A literal character string is not copied with an equal ( = ) assignment. To copy a string, you need to use strcpy(), strncpy(), or one of a number of alternatives.

By using the assignment operator, you lose the address of the memory you malloc'ed, and replace it with the address where "Hello World\n\n\n" is stored (which is likely kept inside the executable itself).
 
Old 05-09-2005, 06:38 PM   #3
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Original Poster
Rep: Reputation: 15
OK, I've changed the program so that it now reads:

Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.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;
  strcpy (TestStructPtr->CharString, "Hello World!\n\n\n");

  printf ("TestStructPtr = (%i, %i).\n\n", TestStructPtr->X, TestStructPtr->Y);
  printf ("CharString = %s.", TestStructPtr->CharString);

  free (TestStructPtr->CharString);
  free (TestStructPtr);

  return 0;
}
With that, gcc is happy, glibc is happy, Valgrind is happy and that makes me happy. Now I just need to figure out where that fits in with my project. Thanks for your help.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
regarding structures eshwar_ind Programming 2 04-25-2005 09:18 AM
Structures AMMullan Programming 6 02-18-2004 11:39 AM
Nested structures :S? alitrix Programming 11 11-15-2003 07:13 PM
Is my malloc/free thinking correct? registering Programming 6 06-18-2003 11:35 PM
C and arrayed structures.. miguetoo Programming 9 05-22-2003 06:30 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:26 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration