您可能知道,每次调用malloc
make OS 都会给您一些内存并记住它的大小和属性。因此,如果您调用free
,您可以清除数组或指针。
例子:
char* array = malloc(16 * sizeof(char));
char* single = malloc(sizeof(char));
free(array);
free(single);
如您所见,您总是free
一对一malloc
。那是因为操作系统知道您分配了多少字节,它并不关心它是什么类型以及创建了多少个实例。(注意:这就是C++delete
和delete[]
C++ 之间存在差异的原因,因为应用程序需要知道要运行哪些析构函数,清理的控制权不仅仅留给操作系统......)
从这里开始,我们可以假设如果我们使用 single 将结构分配为一个块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;
}
当然,如果您遇到更复杂的事情,例如 John Findlay 示例
struct SomeStruct
{
int Size;
int* ArrayOfPointers[];
}
你仍然可以在一个结构中创建这个结构malloc
,例如
// *s* contains an array of 14 int pointers (int*)
struct SomeStruct* s = malloc(sizeof(SomeStruct) + 14 * sizeof(int*));
s->Size = 14;
核心问题是虽然这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));
释放时:
for (int i = 0; i < s->Size; ++i)
free(s->ArrayOfPointers[i]);
free(s);
但关键是,带有 FAM 的结构仍然在一次free
调用中被释放。该循环正在释放分配的指针数据,相当于释放一个动态分配的二维数组。