我正在用 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
我为什么不释放分配?
“为什么我不释放分配?”
如注释中所述,由于使用无法解释的值(幻数)来创建和释放内存,代码中存在额外的复杂性。由于链接中解释的原因以及其他问题,这可能会使释放计数与分配计数的匹配变得困难。由于 Valgrind 指示执行结束时剩余的内存块,因此调用每个函数的时间不匹配。
以下是您的代码和建议,包括明确对
free()
与 [m][c]alloc()
进行相同数量的调用的代码(我选择在此处使用 calloc()
以避免另一个循环(或 memset()
)来初始化记忆。)
另请注意,您可能需要更改此示例用于 #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));
if(game)//test return of malloc before using it.
{
buildfield(game, LENGTH);
printfield(game, LENGTH);
freefield(game, LENGTH);
free(game);
}
else //handle error
{
//do something here to handle error;//
}
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);
}
好在函数buildfield()中 您已分配了 20 个内存块
游戏->字段 = (int **) malloc(sizeof(int *) * 20);
因此,通过 [] 操作符最多可以访问的是 game->field[19] 但在循环中,程序尝试在游戏之前访问更多块->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
}
}
要检查程序是否中途崩溃,请在与访问内存相关的语句末尾添加一些打印语句或使用调试器。因为这是运行时错误最常见的来源。
对于此代码,请尝试记住最大数量。分配的内存块可以通过特定指针访问,并更改标记的 for 循环的条件,以便它将访问分配限制内的内存。使用 malloc 函数分配的块数。
这里的问题不是 free() 不起作用。但是分段错误。 假设您提供的代码与您的代码完全相同