C释放结构指针成员

时间:2017-03-07 10:51:02

标签: c pointers malloc free dynamic-memory-allocation

我有以下结构:

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

在我的main函数中,我尝试使用指向该结构实例的指针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); 

此代码运行良好。但是,我认为当你有一个带有成员指针的结构时,你应该free()每一个(除了指向结构的指针)。

所以在这里,我没有malloc root->data(因为我认为结构malloc会这样做),但它被初始化为输入值并且它& #39; s值成功打印。当我尝试free(root->data)我的程序崩溃时。

root->datamalloc不是malloc root?如果没有,我怎么还能使用它? 为什么会这样?我在这里错过了什么?

4 个答案:

答案 0 :(得分:3)

首先,了解您需要(或不需要)调用free()的位置和方式。

对于“ malloc(),您不需要root->data ”,当您分配的内存等于结构大小时,已经分配了该变量。现在,接下来,你当然需要root->data指向一些有效的内存,这样你就可以取消引用读取的指针来写入它。你可以通过两种方式之一来做到这一点

  • 存储有效的地址(如您的情况,提供已存在变量的地址)
  • 指定另一个malloc()返回的指针(成功)。

如果您存储malloc()返回的指针,是的,您必须free()内存,但在您的情况下,root->data保存malloc()未返回的指针},所以它不需要free() - 。

只是添加并强调与free()相关的部分,必须尝试free()以前未通过调用分配的内存malloc() C11和其他家庭,它会调用undefined behavior。引用,标准void free(void *ptr); ,章节§7.22.3.3,(强调我的

free
     

ptr函数导致ptr指向的空间被释放,即   可供进一步分配。如果free是空指针,则不执行任何操作。否则,如果   该参数与先前由内存管理返回的指针不匹配   功能,或者如果通过调用realloc或{{1}},取消分配空间   行为未定义。

答案 1 :(得分:1)

  

当我尝试释放(root->数据)时,我的程序崩溃了。

您无法free内存未动态分配。如果你想要free元素,你应该先用这种方式分配它们:

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);

请注意,在继续之前,您应该check the result of malloc

  

因此,当我使用malloc root时,root->数据不会被malloced?如果没有,我怎么还能使用它?

另请注意,为root->data分配内存时会分配struct的空间,但不是malloc。您需要额外的malloc,尤其是root->data,如上例所示。您malloc需要root->data的原因是能够取消引用指针。

答案 2 :(得分:1)

input成员指向typedef struct binTreeNode { int *data; struct binTreeNode *left; struct binTreeNode *right; } myBinaryTreeNode; root->data = malloc(sizeof(int)); scanf("%d", root->data); free(root->data); 本地变量,因此您无法释放它。

如果您动态分配成员,则必须释放成员,例如

#include <sched.h>

int main ()
{
    struct sched_attr attr;
    attr.size = sizeof(struct sched_attr);
    attr.sched_policy = SCHED_DEADLINE;
    attr.sched_runtime = 30000000;
    attr.sched_period = 100000000;
    attr.sched_deadline = attr.sched_period;

    if (sched_setattr(gettid(), &attr, 0))
        perror("sched_setattr()");

    return 0;
} 

答案 3 :(得分:1)

我在代码中添加了一些注释。

我希望这能解决问题。

// 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.

您应该真正了解存储持续时间(自动和动态/已分配)以及动态内存分配的目的:

详细解决问题:

  

当我尝试free(root->data)我的程序崩溃时。

这是因为您只能free()拥有malloc()。对于不同类型的存储持续时间,内存管理是不同的。

  

所以当我使用malloc root时,root->data没有被malloced?

指针的内存已分配,但它没有&#34;拥有&#34;或者&#34;指向&#34;默认情况下任何对象。

  

如果没有,我怎么还能使用它?

就像你一样。您为其分配了一个对象的内存地址,它的存在时间足以让您使用它。您可以使用动态内存管理生成此类对象(请注意,一旦完成后手动将其销毁:不要泄漏内存)或使用&#34;自动内存管理&#34;正如你所做的那样(然后注意它不能过早销毁:不要访问无效的内存)。 (仅列举两种创建对象的可能方法......)