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

时间:2021-08-28 21:17:18

I am learning C and I can't free a dynamically allocated array of structs. Here is my sample code:

我正在学习C而且我无法释放动态分配的结构数组。这是我的示例代码:

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). 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"

当我为windows编译它时,一切正常(似乎)。当我使用xcode在我的mac上编译相同的代码时,我得到一个错误,上面写着:“对象0x7fae610060d0的malloc:***错误:没有分配被释放的指针”

How is that possible? I used malloc to create the array... What am I missing here?

怎么可能?我使用malloc来创建数组......我在这里缺少什么?

4 个解决方案

#1


1  

You allocated a flat array of 100 objects. 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.

您分配了一个包含100个对象的平面数组。然后你试图分别释放每个对象和最后的列表 - 这是当你有一个指向对象的指针数组时使用的模式。在您的情况下,您不能释放平面阵列中的一个对象。

You have two options. Keep the flat array and just call free once:

你有两个选择。保持平面阵列,只需拨打一次免费电话:

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)

#2


2  

You need a free for each malloc. How many mallocs you have? 1, so how many free you need? Just 1.

每个malloc都需要免费。你有多少个mallocs? 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);

#3


2  

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)); 

#4


0  

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. So at this point you can use examDB much in the same way as if it was declared struct exam examDB[numRecs].

此表达式分配一个连续的numRecs * sizeof * examDB块,而sizeof * examDB与sizeof struct exam相同。所以在这一点上你可以使用examDB,就像它被声明为struct exam examDB [numRecs]一样。

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一次,你只需要释放一次。

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

#1


1  

You allocated a flat array of 100 objects. 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.

您分配了一个包含100个对象的平面数组。然后你试图分别释放每个对象和最后的列表 - 这是当你有一个指向对象的指针数组时使用的模式。在您的情况下,您不能释放平面阵列中的一个对象。

You have two options. Keep the flat array and just call free once:

你有两个选择。保持平面阵列,只需拨打一次免费电话:

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)

#2


2  

You need a free for each malloc. How many mallocs you have? 1, so how many free you need? Just 1.

每个malloc都需要免费。你有多少个mallocs? 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);

#3


2  

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)); 

#4


0  

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. So at this point you can use examDB much in the same way as if it was declared struct exam examDB[numRecs].

此表达式分配一个连续的numRecs * sizeof * examDB块,而sizeof * examDB与sizeof struct exam相同。所以在这一点上你可以使用examDB,就像它被声明为struct exam examDB [numRecs]一样。

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一次,你只需要释放一次。

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