简体   繁体   中英

C freeing struct pointer members

I have the following structure that I've declared:

typedef struct binTreeNode
{
    void *data;
    struct binTreeNode *left;
    struct binTreeNode *right;  
} myBinaryTreeNode;

In my main function, I'm trying to use a pointer to an instance of that structure called root .

myBinaryTreeNode *root = malloc(sizeof(myBinaryTreeNode));
printf("\nPlease insert root data: ");
int input;
scanf("%d", &input);
root->data = (void*)&input;
printInt(root->data);
free(root); 

this code runs perfectly well. But, I thought that when you have a struct with members that are pointers, you should free() each one of them (additionally to the pointer to the struct).

So here, I didn't malloc for root->data (because I think that malloc ing the struct does that), but it is initialized to the input value and it's value gets printed successfully. When I try to free(root->data) my program crashes.

So root->data is not malloc ed when I malloc root ? If not, how can I still use it? Why does this happen? What am I missing here?

First, get the concept of where and how you need to (or need not) call free() .

You don't need to malloc() "for" root->data , that variable is already allocated while you allocated memory equal to the size of the structure. Now, next, you certainly need root->data to point to some valid memory, so that you can dereference the pointer to read from to write into it. You can do that by either of two ways

  • store an address which is valid (like in your case, supply the address of an already existing variable)
  • assign a pointer returned by another malloc() (success).

In case, you're storing the pointer returned by malloc() , yes you must free() the memory but in your case, root->data holds a pointer not returned by malloc() , so it does not need free() -in either.

Just to add and emphasis on the part related to free() -ing, you must not attempt to free() the memory which has not been previously allocated by a call to malloc() and family otherwise, it invokes undefined behavior . To quote, standard C11 , chapter §7.22.3.3, ( emphasis mine )

 void free(void *ptr); 

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc , the behavior is undefined.

When I try to free(root->data) my program crashes.

You cannot free memory that you have not dynamically allocated. If you want to free the elements, you should first allocate them this way :

typedef struct binTreeNode
{
    int *data;
    struct binTreeNode *left;
    struct binTreeNode *right;  
} myBinaryTreeNode;

root->data = malloc(sizeof(int));
if (root->data == NULL)
{
    printf("Error allocating memory\n");
    return;
}
scanf("%d", root->data);
free(root->data);

Note that you should check the result of malloc before continuing.

So root->data is not malloced when I malloc root? If not, how can I still use it?

Note also that space for root->data is allocated when you allocate memory for the struct , but it is not malloc ed. You need an extra malloc especially for root->data , as shown in the example above. The reason why you need malloc for root->data is to be able to dereference the pointer.

data member points to input local variable, so you cannot free it.

You must free members if you dynamically allocate them, like

typedef struct binTreeNode
{
    int *data;
    struct binTreeNode *left;
    struct binTreeNode *right;  
} myBinaryTreeNode;

root->data = malloc(sizeof(int));
scanf("%d", root->data);
free(root->data);

I have added some annotations to your code.

I hope this clears things up.

// I have added an enclosing block for the purpose of demonstration:
{
    // Here you allocate memory for a tree node object with dynamic/allocated 
    // storage duration.
    // That is: three pointers, that point to nowhere are created and will
    // exist until the memory holding them is free'd.
    myBinaryTreeNode *root = malloc(sizeof(myBinaryTreeNode));
    printf("\nPlease insert root data: ");
    // Here you create an object with automatic storage duration.
    // That is, the object is automatically destroyed when the function
    // returns or the block is closed: { ... }
    int input;
    // here you attempt to assign a value to the variable
    // (you should check the return value: the input may fail)
    scanf("%d", &input);
    // Here you assign the address of an object to a pointer.
    // Note that you are only allowed to use the pointer as long as the
    // object it points to "lives".
    root->data = (void*)&input;
    // Here you probably print the value, or the pointer address, or something else
    printInt(root->data);
    free(n); // <-- Where and how did you allocate this?
    // Here you free the memory holding the tree node
    free(root); 
} // <-- At this point the "input" variable is automatically destroyed.

You should really read up on the different storage durations (automatic and dynamic/allocated) and the purpose of dynamic memory allocation :


To address the questions in detail:

When I try to free(root->data) my program crashes.

That is because you can only free() what you have malloc() . Memory management is different for the different types of storage duration.

So root->data is not malloced when I malloc root?

Memory for the pointer is allocated, but it doesn't "own" or "point to" any object by default.

If not, how can I still use it?

Just as you did. You assign a memory address of an object to it, that lives long enough for you to use it. You can produce such object using dynamic memory management (then take care that you destroy it manually once you're done: don't leak memory) or using "automatic memory management" as you have done (then take care that it isn't destroyed too early: don't access invalid memory). (To name just two of the possible ways to create an object...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM