在c中struct的成员中间调用free时会发生什么?

问题描述 投票:0回答:1

我只是想知道今晚free()调用struct成员时会发生什么。让我们看一下c中的简单代码。

typedef struct {
    int c[5];
    int a[10];
    int *b;
}stma;
int main() {
    stma *he = (stma*)malloc(sizeof(stma));
    int *ac = he->a;
    free(ac); //This point is crash.
    return 0;
}

免费制造崩溃。但是下一个代码运行良好。

typedef struct {
    int c[5];
    int a[10];
    int *b;
}stma;
int main() {
    stma *he = (stma*)malloc(sizeof(stma));
    int *ac = he->c; //This point is changed.
    free(ac); //Work well.
    return 0;
}

当然,我认为第二个可以正常工作,第一个也不是正确的代码。

我想知道在第一次执行期间会发生什么。 free()free'a'变量,struct的中间,不是struct的地址。

he-> a不是malloced,动态分配,不能免费。在这种情况下,he-> c存储器地址为00D2Ad50,而he-> a为00D2AD64。 struct变量将由malloc()放在堆中。他 - > c的地址与'他'相同。而他 - > c + 4 * 5是他 - > a。他 - > a也在堆里?那么,免费会发生什么(他 - > a)?

c struct malloc free
1个回答
6
投票

你的第一个例子是undefined behavior。你试图释放你从内存管理功能(malloc)得到的东西。并且像未定义的行为意味着 - 它可能崩溃,工作或任何事情 - 标准不指定行为。所以一切都可能发生。

来自§7.22.3.3¶2

否则,如果参数与先前由内存管理函数返回的指针不匹配,或者如果空间已通过调用free或realloc释放,则行为未定义。

您的第二个示例不是未定义的行为,并且完全合法 - 这可以通过下面给出的引用进行验证。来自§6.7.2.1¶15N1570

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单位,反之亦然。结构对象中可能存在未命名的填充,但不是在其开头。

由于没有涉及填充,因此第一个成员的地址必然是之前调用的malloc返回的地址。通过前面提到的关于free的引用,这没关系。

还有一点要做 - 没有强制转换malloc的返回值并检查malloc的返回值。

1.当你试图从分配对象的中间释放内存或者你根本没有使用内存管理函数释放内存.int *a = malloc(sizeof*a * 5)然后调用free(&a[5])这将是未定义的行为甚至这个int a[10];然后叫free(&a[5])就是一个。对于动态分配,您始终可以使用realloc缩小分配的空间(释放不需要的内存。)

© www.soinside.com 2019 - 2024. All rights reserved.