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 free
ing or delete
ing (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 free
d 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 = ▭//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;
}