【问题标题】:C: free memory allocated in cC:在c中分配的空闲内存
【发布时间】:2015-03-21 02:54:21
【问题描述】:

假设我有一个结构:

typedef struct{
    char *ID;
    char *name;
    float price;
    int quantity;
} Generic_Properties;

现在,如果我使用 malloc 为其在堆中分配空间并将地址保存在指针中,让我们称他为 p1。现在我想释放那个特定的内存块,只声明free(p1)就足够了:

free(p1);

或者我是否需要分别释放 ID 和名称指针,因为我使用 malloc 为它们指向的字符串分配空间?

【问题讨论】:

  • malloc 所需的一切free
  • 正如@JoachimPileborg 所说。加注:您通常需要free ID 和名称,然后再使用free 属性结构(除非您在某处保留那些指针的副本),因为IDname 成员变量一旦您就无效释放了它们所属的结构。

标签: c pointers malloc free


【解决方案1】:

规则是,mallocfree 应该成对出现。只释放一次malloced 的所有内容。

char name[] = "some_name";
Generic_Properties *p1 = malloc(...);  /* 1 */
p1->ID = malloc(...); /* 2 */
p1->name = name;
...
...
/* free(p1->name); Don't do this, p1->name was not allocated with malloc*/
free(p1->ID);  /* 2' */
free(p1); /* 1' */
/* if(p1 && p1->name[0] == '?') {} don't dereference p1 after it is freed. It is dangling now */
...
...
/* free(p1); don't free p1 again as it is already freed and is dangling. */
p1 = NULL;
free(p1); /* OK */

【讨论】:

    【解决方案2】:

    或者我是否需要分别释放 ID 和名称指针,因为我使用了 malloc 为他们指向的字符串分配空间?

    正如 Mohit Jain 所指出的,每次调用 malloc 之后都必须调用 free,但在这种情况下(请参阅下面的 cmets),没有什么可以阻止您在一次调用中为所有内容保留空间:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    typedef struct{
        char *ID;
        char *name;
        float price;
        int quantity;
    } Generic_Properties;
    
    int main(void)
    {
        Generic_Properties *x = malloc(sizeof(*x) + 100);
        x->ID = (char *)(x + 1);
        x->name = x->ID + 50;
    
        strcpy(x->ID, "00001");
        strcpy(x->name, "David");
        printf("%s %s\n", x->ID, x->name);
        free(x);
        return 0;
    }
    

    【讨论】:

    • 这真是明智:)
    • 在一般情况下,这里可能存在对齐问题(例如,如果 ID 不是 char* 而是 long long*)。
    • @TimČas,我也这么认为,但是take a look
    • @AlterMann:他的理由仅适用于包含int*, int* 的非常具体的结构——其中int* 的对齐(在大多数相关拱门中)至少4 个字节,同样适用于int。换句话说,保证对齐是正确的在特定情况下。将int* 替换为long long*,你就有麻烦了:比如说,在x86 中,long long 有(比如说)8 字节对齐,而T* 仍然是4 字节。
    • @AlterMann:是的。但是,当您将 sizeof(Foo) 添加到该地址 (4) 时,它不再正确对齐。换句话说,malloc(...) 是对齐的,malloc(...)+x 不是(好吧,反正不一定)。
    【解决方案3】:

    处理这种结构的更面向对象的方法是定义用于分配和释放这种结构的函数。

    (此代码的改进版本)

    // Allocate a GP object
    Generic_Properties * create_GP()
    {
        Generic_Properties *  p;
    
        p = malloc(sizeof(Generic_Properties));
        memset(p, 0, sizeof(*p));
        return p;
    }
    
    // Deallocate a GP object
    void free_GP(Generic_Properties *p)
    {
        if (p == NULL)
            return;
    
        free(p->ID);
        p->ID = NULL;
    
        free(p->name);
        p->name = NULL;
    
        free(p);
    }
    

    附录

    如果您想将此方法与@Alter Mann 的方法结合使用,您可以这样做:

    // Allocate a GP object
    Generic_Properties * create_GP2(const char *id, const char *name)
    {
        size_t                idLen;
        size_t                nameLen;
        Generic_Properties *  p;
    
        // Reserve space for GP, GP.ID, and GP.name
        //  all in one malloc'd block
        idLen = strlen(id) + 1;
        nameLen = strlen(name) + 1;
        p = malloc(sizeof(Generic_Properties) + idLen + nameLen);
        memset(p, 0, sizeof(*p));
    
        // Save the ID
        p->ID = (char *)p + sizeof(Generic_Properties);
        memcpy(p->ID, id, idLen);
    
        // Save the name
        p->name = p->ID + idLen;
        memcpy(p->name, name, nameLen);
        return p;
    }
    
    // Deallocate a GP object
    void free_GP2(Generic_Properties *p)
    {
        free(p);
    }
    

    【讨论】:

    • 您不需要if (p-&gt;ID != NULL) 条件。做free(NULL) 完全没问题
    • 啊,我忘记了free()的那个功能。我已将上面的代码编辑为相应的改进版本。
    猜你喜欢
    • 2012-09-18
    • 2011-07-13
    • 1970-01-01
    • 2014-11-24
    • 2013-05-02
    • 1970-01-01
    • 2018-10-09
    • 2015-04-29
    • 2012-06-19
    相关资源
    最近更新 更多