[英]Free Memory of 2d Array in struct
我正在 C 写一个小游戏,我想用 Valgrind 测试它。 这是一个小代码示例:
#include <stdio.h>
#include <stdlib.h>
typedef struct Game {
int** field;
} Game;
void buildfield(Game* game, int length);
void printfield(Game* game, int length);
void freefield(Game* game, int length);
int main()
{
struct Game* game = NULL;
game = malloc(sizeof (struct Game));
buildfield(game, 10);
printfield(game, 10);
freefield(game, 10);
free(game);
return 0;
}
void buildfield(Game* game, int length)
{
game->field = (int**)malloc((sizeof (int*)) * 20);
int i;
for (i = 0; i < 20; i++) {
game->field[i] = (int*) malloc((sizeof (int)) * length);
}
for (int line = 0; line < length; line++) {
for (int col = 0; col < 81; col++) {
game->field[col][line] = 0;
}
}
}
void printfield(Game* game, int length)
{
for (int i = 0; i < length; i++) {
printf("\n");
for (int j = 0; j < 20; j++) {
printf("%d",game->field[i][j]);
}
}
}
void freefield(Game* game, int length)
{
for (int i = 0; i < length; ++i) {
free(game->field[i]);
}
free(game->field);
}
Valgrind 说:
HEAP SUMMARY:
==6239== in use at exit: 968 bytes in 22 blocks
==6239== total heap usage: 22 allocs, 0 frees, 968 bytes allocated
为什么我不释放分配?
那么在 function buildfield() 你已经分配了 20 个块 memory
game->field = (int **) malloc(sizeof(int *) * 20);
因此,您最多可以通过 [] 运算符访问 game->field[19] 但是在循环中,程序会尝试在 game->field[19] 之前访问更多块,从而导致分段错误并且程序会在那里崩溃。 无需返回 main(),更不用说到达 free() 语句了。 所以这意味着你的程序一开始就没有完成并且中途崩溃了。
for (int line = 0; line < length; line++)
{
for (int col = 0; col < 81; col++) //when col becomes 20
{
game->field[col][line] = 0; //this statement will try to access the non-alloted memory block when col is 20
}
}
要检查您的程序是否中途崩溃,请在与访问 memory 相关的语句末尾添加一些打印语句或使用调试器。 因为这是最常见的运行时错误来源。
同样对于此代码,请记住最大编号。 分配的 memory 个块中,可以由特定指针访问,并更改标记的 for 循环的条件,以便它将在分配限制内访问 memory,即第 2 个。 您使用 malloc function 分配的块数。
这里的问题不是 free() 不工作。 但是分段错误。 假设您提供的代码是您的代码的精确副本
“为什么我不释放分配?”
如评论中所述,由于使用无法解释的值( 幻数)创建和释放 memory,导致代码更加复杂。由于链接中解释的原因,除其他问题外,这可以使匹配的释放计数与计数分配困难。 由于 Valgrind 指示在执行结束时剩余的 memory 块,因此调用这些中的每一个的时间不匹配。
以下是您的代码和建议,包括那些明确应用与[m][c]alloc()
相同数量的调用free()
的代码(我选择在此处使用calloc()
以避免另一个循环(或memset()
) 来初始化 memory。)
另请注意,您可能需要更改此示例用于 #defines 的值以满足您的需要,但您只需在一个地方(在文件顶部)更改它们。
typedef struct Game {
int** field;
} Game;
void buildfield(Game *game, int length);
void printfield(Game *game, int length);
void freefield(Game *game, int length);
#define COUNT 20//replace all magic numbers
#define LENGTH 10//(change values of #defines to change shape and size of memory)
int main(void)//use a complete prototype for main
{
struct Game* game = NULL;//pointer needs memory
game = malloc(sizeof (struct Game));
buildfield(game, LENGTH);
printfield(game, LENGTH);
freefield(game, LENGTH);
free(game);
return 0;
}
void buildfield(Game *game, int length)
{ //Note - not optimal to cast return of [c][m]alloc in C (only in C++)
game->field = calloc(COUNT, sizeof(game->field));
int i;
for (i = 0; i < COUNT; i++) {
game->field[i] = calloc(LENGTH, (sizeof (game->field[i])) );
}
}
void printfield(Game *game,int length)
{
for (int i = 0; i < COUNT; i++) {
printf("\n");
for (int j = 0; j < LENGTH; j++) {
printf("%d",game->field[i][j]);
}
}
}
void freefield(Game *game,int length)
{
for (int i = 0; i < COUNT; ++i) {
free(game->field[i]);
}
free(game->field);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.