【发布时间】:2021-11-19 14:10:48
【问题描述】:
我正在用 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
我为什么不释放分配?
【问题讨论】:
-
for(i = 0; i < 20; i++)你分配了 20 个字段,但freefield(game, 10);只释放了 10 个字段 -
for(i = 0; i < 20; i++)和freefield(game, 10):使用 contants 或#defines 代替硬编码数字,例如:#define NBFIELDS 20和for(i = 0; i < NBFIELDS; i++)和freefield(game, NBFIELDS) -
在
for (int col = 0; col < 81; col++)- 你没有80列就够了,所以有一个越界访问,即未定义行为。 -
当我运行你的代码时,我得到了一个分段错误(@Ruks 上面提到的部分)所以当然
free()永远不会被调用,因为程序在那之前崩溃了。 -
如果您停止使用“幻数”并改用命名变量/常量,这段代码中的所有问题都会消失。