使用灵活的阵列成员释放动态分配的结构

Pat*_*ite 3 c malloc dynamic-allocation

我有一个数据结构,定义如下:

struct varr {
    int n; //length of data array
    double data[];
};
Run Code Online (Sandbox Code Playgroud)

数据阵列最初需要大小为1,但允许增加的可能性.

struct varr *我分配空间时使用

struct varr *p = malloc(sizeof(struct varr) + sizeof(double));
Run Code Online (Sandbox Code Playgroud)

重新分配空间以增加我使用的数据数组的大小

p = realloc(p, sizeof(struct varr) + p->n * sizeof(double));//p->n having already been set
Run Code Online (Sandbox Code Playgroud)

我的问题是"我应该如何释放为此结构分配的内存?"

我尝试过一个简单free(p);但根据memcheck导致内存泄漏的问题.对于我为此目的构建数据的方式,或者我如何分配内存,是否存在根本性的错误?

== ==注意

我通过使用指针而不是显式声明的数组解决了这个问题.然而,我仍然对一个简明的答案感兴趣,为什么这不起作用.

Zde*_*nek 5

首先,@ Waanton的John Findlay例子与此无关.THESTRUCT他使用的实际上是一个指针数组,因此他首先需要释放所有指针然后释放结构.

回到主题:
正如您可能知道的那样,每次调用mallocOS都会给你一些记忆并记住它的大小和属性.因此,如果您调用free,则可以清除数组或指针.

例子:

char* array = malloc(16 * sizeof(char));
char* single = malloc(sizeof(char));

free(array);
free(single);
Run Code Online (Sandbox Code Playgroud)

如你所见,你总能得到free一对一malloc.这是因为OS知道你分配了多少字节,它不关心它是什么类型以及创建了多少个实例.(注:这就是为什么有差异delete,并delete[]在C++中,因为应用程序需要知道跑什么析构函数,清理的控制不仅是留给操作系统...)

从这里开始,我们可以假设如果我们使用单个结构将结构分配为一个块malloc,则可以使用单个free调用释放它.

这个例子对我没有任何泄漏:

#include <stdlib.h>

typedef struct Array_t
{
    int Length;
    double Data[];
} Array;

Array* create_array(int length)
{
    Array* array = malloc(sizeof(Array) + length * sizeof(double));
    if (array != NULL)
        array->Length = length;

    return array;
}

void delete_array(Array* array)
{
    free(array);
}

int main()
{
    Array* array = create_array(100);
    if (array == NULL)
        return EXIT_FAILURE;

    for (int i = 0; i < array->Length; ++i)
    {
        array->Data[i] = 1.7 * (i + 3);
    }

    delete_array(array);

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

当然,如果你能达到像约翰·芬德利这样复杂的东西

struct SomeStruct
{
    int Size;
    int* ArrayOfPointers[];
}
Run Code Online (Sandbox Code Playgroud)

你仍然可以在一个结构中创建这个结构malloc,例如

// *s* contains an array of 14 int pointers (int*)
struct SomeStruct* s = malloc(sizeof(SomeStruct) + 14 * sizeof(int*));
s->Size = 14;
Run Code Online (Sandbox Code Playgroud)

核心问题是虽然这int* ArrayOfPointers是一个指针数组,因此要正确初始化它,您还需要

// each of the *s*'s int pointers is actually a decayed array of 25 ints
for (int i = 0; i < s->Size; ++i)
    s->ArrayOfPointers[i] = malloc(25 * sizeof(int));
Run Code Online (Sandbox Code Playgroud)

并在释放时:

for (int i = 0; i < s->Size; ++i)
    free(s->ArrayOfPointers[i]);

free(s);
Run Code Online (Sandbox Code Playgroud)

但问题是,在一次free通话中仍然可以释放具有FAM的结构.循环释放分配的指针数据,这相当于释放动态分配的2D数组.