混淆于malloc和free的行为

5

我对在C语言中使用free()释放数据结构感到困惑。

如果我有以下数据结构:

struct Person {
    char *name;
    int age;
    float weight;
    float height;
};

我通过malloc()为结构体分配内存,例如:struct Person *me = malloc(sizeof(struct Person));

在使用完我的结构体后(程序结束之前),我会释放已分配的内存,方法如下:

free(person_pointer->name);
free(person_pointer);

释放 name 指针所指向的内存是必要的,因为如果我只释放 person_pointer 的内存,我只会释放用于存储数据结构及其成员的内存但不会释放结构体成员指针所指向的内存。 然而,使用我的实现,valgrind 似乎表明第一个 free() 是无效的。
所以,我的问题归结为:当我通过指针释放结构体占用的内存时,是否应该预先释放成员指针所指向的内存? 编辑:这是我的整个代码:
#include <stdio.h>
#include <stdlib.h>

struct Person {
    char *name;
    int age;
    float weight;
    float height;
};

int main(int argc, char **argv)
{
    struct Person *me = malloc(sizeof(struct Person));
    me->name = "Fotis";
    me->age = 20;
    me->height = 1.75;
    me->weight = 75;

    printf("My name is %s and I am %d years old.\n", me->name, me->age);
    printf("I am %f meters tall and I weight %f kgs\n", me->height, me->weight);

    free(me->name);
    free(me);

    return 0;
}

@Mat 我使用 malloc()。我会编辑问题以澄清这一点。 - NlightNFotis
@Mat 我刚刚更新了问题并附上了我的分配方法。如果您需要更多信息,我可以发布整个代码,它是一个相当小的程序,但从现在开始为了清晰起见,我将不再这样做。 - NlightNFotis
1
使用Valgrind等工具,对测试用例进行完整测试,确保代码质量。 - Oliver Charlesworth
@MM.:没错。me->name 指向一个匿名字符串。 - md5
4个回答

5
me->name = "Fotis";

/* ... */

free(me->name);

规则如下:
1 malloc = 1 free

你没有在me->name上使用malloc,所以不需要free它。

另外,me->name应该是const char *类型。


1

如果你分配了指针内存,那么你必须释放结构体中所有指针的内存。

同时确保在释放结构体之前先释放成员。

一个简单的记忆方法是按照你分配的相反顺序逐个释放它们。


1
当你执行


    me->name = "Fotis";

name指针并非由malloc分配,它指向存储在编译时的二进制文件的字符串表中的堆栈变量,因此您无法释放它。

经验法则是:只释放您已经使用malloc分配的内存。

但您无法更新此只读字符串。

如果您执行以下操作:

me->name = strdup("Fotis");

由于strdup会进行内存分配(请参阅手册),因此您需要释放它,并且可以在创建后更新字符串。

1
问题在于你没有在结构体内部实际分配 char * name 的内存空间。
struct Person *me = malloc(sizeof(struct Person));
me->name = strdup("Fotis");
...
free(me->name);
free(me);
return (0);

当你写这个时

me->name = "Fotis";

您实际上并没有使用malloc函数,指针名称指向的是一个类型为const char *的栈变量,它并没有被动态分配内存。


3
strdup 不是标准库函数。最好不要推荐它... - Oliver Charlesworth
字符串字面值是静态存储的,不在堆栈上。它的指针在程序中的任何函数中都是有效的。 - teppic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接