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