Home > database >  Does a pointer inside a struct get freed automatically when the struct variable is freed?
Does a pointer inside a struct get freed automatically when the struct variable is freed?

Time:01-27

I have something like this:-

struct Pos {
    float x, y;
};
struct Rect {
    struct Pos* pos;
    int width, height;
};

I have created a pointer of Rect, so when I will free this pointer using free(), then will it also free pos?

CodePudding user response:

No; everything you manually allocate, you manually deallocate. This makes dynamic 2D (and more) arrays somewhat tedious to code, requiring:

 int **array = malloc(NUM_ROWS * sizeof(int *));
 if(NULL == array)
 {
     // Handle out of memory error
 }
 for(int i = 0; i < NUM_ROWS; i  )
 {
     array[i] = malloc(NUM_COLS * sizeof(int));
     if(NULL == array[i])
     {
         // Handle out of memory error
     }
 }

To allocate, then:

for(int i = 0; i < NUM_ROWS; i  )
{
    free(array[i]);
    array[i] = NULL;
}
free(array);
array = NULL;

To deallocate. If you manually allocate pos, you manually deallocate pos before you deallocate its parent struct Rect if that's what it's in:

free(someRect.pos);
someRect.pos = NULL;
free(someRect);
someRect = NULL;

I always set pointers to NULL(ptr) after freeing or deleteing (C ) them.

CodePudding user response:

I have created a pointer of Rect, so when I will free this pointer using free(), then will it also free pos?


Assuming the pointer to struct Rect was allocated on the heap with one of the memory allocation function (so that it can be freed legitimately), then free() will only release the memory for the structure that was pointed at, not the nested pointers.

You must free() the pointer pos before free()ing the pointer to the struct, else you'll lose access to the memory allocated through pos, and leak it.

Every object you malloc(), must later be released with free(). It doesn't happen for you automatically.

See also: When you exit a C application, is the malloc-ed memory automatically freed?

CodePudding user response:

Assuming you do something like

struct Rect *r = malloc( sizeof *r );
r->pos = malloc( sizeof *r->pos );
...
free( r );

then no, this will not free the memory that r->pos points to. You must make sure to deallocate r->pos before deallocating r:

free( r->pos );
free( r );

It's usually a good idea to abstract out the allocation and deallocation for types that require multiple allocation and free operations:

struct Rect *newRect( void )
{
  struct Rect *r = malloc( sizeof *r );
  if ( r )
  {
    r->pos = malloc( sizeof *r->pos );
    /**
     * If we can't successfully allocate r->pos, 
     * deallocate anything we've allocated
     * so far and return NULL.
     */
    if ( !r->pos )
    {
      free( r );
      r = NULL;
      fputs( "Failed to allocate internal member\n", stderr );
    }
  }
  return r;
}

void freeRect( struct Rect *r )
{
  free( r->pos );
  free( r );
}

CodePudding user response:

Note, this is an aside, as it does not address your primary question.
But given your description

"I have created a pointer of Rect"

I wanted to point out that it is possible to use this pointer variable without having to free its memory. Just point it to a location created on the stack. So given your definitions, here is how that would work:

struct Pos {
    float x, y;
};
struct Rect {
    struct Pos* pos;
    int width, height;
};

int main(void) {
   
    struct Rect rect = {0};
    struct Rect *pRect = &rect;//point pointer to location created on the stack
    pRect->pos = malloc(10*sizeof(struct Pos));// allocate only pointer
                                               // member of struct Pos
    if(pRect->pos)
    {
        //do something with rect.pos
        for(int i=0;i<10;i  )
        {
            pRect->pos[i].x = (i 1.0)*1.0; 
            pRect->pos[i].y = pRect->pos[i].x * pRect->pos[i].x;
        }
        //free rect.pos when finished
        free(pRect->pos);//only need to free the pointer member of struct Pos
        //no need to free pRect as it points to memory created on stack
    }
    return 0;
}
  • Related