释放C中的结构还会删除其成员吗?

时间:2019-05-01 13:44:22

标签: c malloc free

我是C语言的新手,我有一个关于分配内存的问题。因此,我在下面尝试了这段代码,该代码应该释放elem1结构。

struct elem{

    char *data1;
    char *data2;

};

int main()
{

    struct elem *elem1 = malloc(sizeof(struct elem));
    elem1->data1 = "abc";
    elem1->data2 = "def";
    char *a = elem1->data1;
    char *b = elem1->data2;
    free(elem1);

    printf("%s\n%s\n",a,b);
    return 0;
}

代码可以很好地编译并返回,

abc 
def

我希望它会失败,因为free也应该释放其成员的内存。但是为什么行得通呢?释放结构后,如果要访问结构的成员该怎么办?

2 个答案:

答案 0 :(得分:9)

成员是结构的一部分。释放结构会释放其所有成员。

但是,在您的示例中,成员只是指针。您正在将指针复制到结构(node->data1 = ...)中,然后从结构(... = node->data1)中复制出来,然后释放结构。这些都不会影响指针指向的内存。

在您的示例中,实际的字符串存储在静态内存中(它们是字符串文字)。这意味着它们永远不会被摧毁。只要程序运行,它们就一直存在。这就是为什么打印它们绝对安全。您的代码很好。

最后,访问已释放的内存具有未定义的行为(意味着任何事情都可能发生,包括程序崩溃或看起来正常工作)。如果要访问已释放的结构的成员,只需执行以下操作:

struct elem *p = malloc(sizeof *p);
free(p);
p->data1 = "boom!";  // Undefined behavior!

但是,那将是一个错误,所以……请不要。

答案 1 :(得分:7)

每个 malloc必须与相应的free保持平衡。

您的分配node->data1 = "abc";分配了一个指向只读文字"abc"的指针,因此这里没有动态内存,因此您不能使用{{1 }}。

在特定情况下,您可以保留指针freea上调用了free的指针,因为您不必{{1 }}该内存,它从来都不属于struct。但这通常不起作用:如果您使用free来设置struct,则(1)您必须在之前对该指针调用malloc尝试在node->data1上调用free,并且(2)后续free的引用的行为将是不确定的。