简体   繁体   English

如何释放C中动态分配的结构数组?

[英]How to free a dynamically allocated array of structs in c?

I am learning C and I can't free a dynamically allocated array of structs. 我正在学习C,无法释放动态分配的结构体数组。 Here is my sample code: 这是我的示例代码:

typedef char Str50[50];

typedef struct exam {
    Str50 firstname;
    Str50 lastname;
    Str50 className;
    int score;
    Str50 date;
} Exam;

Exam *examDB

size_t allocateAndFreeTheStructArray {

    size_t numRecs = 100; //let's say the array contains 100 elements
    examDB = malloc(numRecs * sizeof * examDB); //this allocates the needed memory

    // the code below tries to free what malloc allocated
    for (size_t i = 0; i < numRecs; i++) {
        free(&examDB[i]);
    }
    free(examDB);
}

When I compile this for windows, everything works fine (it seems). 当我为Windows编译时,一切正常(看来)。 When I compile the same piece of code on my mac using xcode, I get an error that says: "malloc: *** error for object 0x7fae610060d0: pointer being freed was not allocated" 当我使用xcode在Mac上编译同一段代码时,出现错误消息:“ malloc:对象0x7fae610060d0的错误:未分配释放的指针”

How is that possible? 那怎么可能? I used malloc to create the array... What am I missing here? 我使用malloc创建了数组...我在这里想念什么?

You need a free for each malloc . 您需要为每个malloc free How many malloc s you have? 您有多少个malloc 1, so how many free you need? 1,您需要多少free Just 1. 只是1。

You are allocating an array of 100 * sizeof(examDB) elements, which is dynamic but each element is a examDB , not a pointer to an examDB so you just need to free the whole array. 您正在分配一个由100 * sizeof(examDB)元素组成的数组,该数组是动态的,但每个元素都是一个examDB ,而不是指向examDB的指针,因此您只需要释放整个数组即可。

You would have required to free each element of the array if you had something like 如果您有类似的东西,您将需要释放数组的每个元素

// 1 malloc
examDB** array = malloc(sizeof(examDB*) * 100);

// 100 malloc
for (int i = 0; i < 100; ++i)
  examDB[i] = malloc(sizeof(examDB));

...

// 100 free
for (int i = 0; i < 100; ++i)
  free(examDB[i]);

// 1 free
free(examDB);

You allocated an array of objects. 您分配了一个对象数组。 You can't free them by elements. 您不能按元素释放它们。 What you can do is just free examDB itself: 您可以做的就是免费的examDB本身:

 free(examDB);

The reason to do this is, as I said before, you are allocating a whole array of null values, as this code you posted states: 这样做的原因是,正如我之前说的,您正在分配整个空值数组,因为您发布的这段代码指出:

examDB = malloc(numRecs * sizeof * examDB); 

What you can do to free element by element is to initialize your allocated elements like this: 要释放一个元素一个元素,您可以做的是初始化分配的元素,如下所示:

for (int i = 0; i < 100; ++i)
  examDB[i] = malloc(sizeof(examDB));

Here is a C++ reference for malloc . malloc的C ++参考。

Tip : I have never seen this malloc invoked like this: 提示 :我从未见过这样调用过malloc

malloc(numRecs * sizeof * examDB); 

It's more common to put it this way: 这种说法更常见:

malloc(numRecs * sizeof(examDB)); 

You allocated a flat array of 100 objects. 您分配了100个对象的平面数组。 You're then trying to free each object separately and the list at the end - that's a pattern used when you have an array of pointers to objects. 然后,您尝试分别释放每个对象,最后释放列表-这是当您有指向对象的指针数组时使用的模式。 In your case, you can't free just one object in a flat array. 就您而言,不能只free平面数组中的一个对象。

You have two options. 您有两个选择。 Keep the flat array and just call free once: 保留平面数组,只需拨打一次free电话:

size_t numRecs = 100; 
examDB = malloc(numRecs * sizeof * examDB); 

free(examDB);

Or change examDB to a pointer to pointer to Exam to keep a list of pointers: 或将examDB更改为指向Exam指针,以保留指针列表:

Exam **examDB;

and then this would be the valid code: 然后这将是有效的代码:

size_t numRecs = 100; 
examDB = malloc(numRecs * sizeof * examDB); 

for (size_t i = 0; i < numRecs; i++) {
    examDB[i] = malloc(sizeof ** examDB);
}

for (size_t i = 0; i < numRecs; i++) {
    free(&examDB[i]);
}
free(examDB);

BTW, this must be one of the most confusing malloc invocations I've ever seen: 顺便说一句,这一定是我见过的最令人困惑的malloc调用之一:

malloc(numRecs * sizeof * examDB)
examDB = malloc(numRecs * sizeof * examDB); //this allocates the needed memory

This expression allocates a single contiguous block of numRecs * sizeof *examDB , and sizeof *examDB is the same as sizeof struct exam . 该表达式分配一个连续的numRecs * sizeof *examDB块,而sizeof *examDBsizeof struct exam相同。 So at this point you can use examDB much in the same way as if it was declared struct exam examDB[numRecs] . 因此,在这一点上,您可以像使用 struct exam examDB[numRecs]一样使用 examDB

Calls to free should be paired with calls to malloc and since you only malloc once, you only need to free once. free调用应与对malloc调用配对使用,并且由于您仅对malloc一次,因此只需对free一次调用。

 examDB = malloc(numRecs * sizeof * examDB); //this allocates the needed memory
 //...
 free(examDB);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM