简体   繁体   English

结构中二维数组的免费 Memory

[英]Free Memory of 2d Array in struct

I'm writing a little game in C and I wanted to test it with Valgrind.我正在 C 写一个小游戏,我想用 Valgrind 测试它。 Here is a little code example:这是一个小代码示例:

#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 is saying: Valgrind 说:

HEAP SUMMARY:
==6239==     in use at exit: 968 bytes in 22 blocks
==6239==   total heap usage: 22 allocs, 0 frees, 968 bytes allocated

Why don't I free the allocations?为什么我不释放分配?

Well in the function buildfield() You have alloted 20 blocks of memory那么在 function buildfield() 你已经分配了 20 个块 memory

game->field = (int **) malloc(sizeof(int *) * 20); game->field = (int **) malloc(sizeof(int *) * 20);

Hence the most you can access by [] operator is game->field[19] But in the loop the program tries to access more blocks ahead of game->field[19] Causing a segmentation fault And the program crashes then and there.因此,您最多可以通过 [] 运算符访问 game->field[19] 但是在循环中,程序会尝试在 game->field[19] 之前访问更多块,从而导致分段错误并且程序会在那里崩溃。 Without ever returning to main() let alone reach the free() statement.无需返回 main(),更不用说到达 free() 语句了。 So it means your program never completed in the first place and crashed midway.所以这意味着你的程序一开始就没有完成并且中途崩溃了。

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
    }
}

To check if your program crashes midway add some print statements at the end of the statements related to accessing memory or use a debugger.要检查您的程序是否中途崩溃,请在与访问 memory 相关的语句末尾添加一些打印语句或使用调试器。 Because that's the most common source of runtime errors.因为这是最常见的运行时错误来源。

Also for this code try to keep in mind the maximum no.同样对于此代码,请记住最大编号。 of memory blocks alloted that can be accessed by a specific pointer and change the condition of the marked for loop so that it will access memory within the allocation limit that is the no.分配的 memory 个块中,可以由特定指针访问,并更改标记的 for 循环的条件,以便它将在分配限制内访问 memory,即第 2 个。 of blocks you alloted using the malloc function.您使用 malloc function 分配的块数。

The problem here is not the free() not working.这里的问题不是 free() 不工作。 But the segmentation fault.但是分段错误。 Assuming the code you provided is the exact replica of your code假设您提供的代码是您的代码的精确副本

"Why don't I free the allocations?" “为什么我不释放分配?”

As noted in comments, there is extra complication in the code caused by use of unexplained values ( magic numbers ) to both create and free memory. For reasons explained in the link, among other problems, this can make matching count of frees with count of allocations difficult.如评论中所述,由于使用无法解释的值( 幻数)创建和释放 memory,导致代码更加复杂。由于链接中解释的原因,除其他问题外,这可以使匹配的释放计数与计数分配困难。 The mis-match in times each of these is called in the reason Valgrind indicated blocks of memory remaining at the end of execution.由于 Valgrind 指示在执行结束时剩余的 memory 块,因此调用这些中的每一个的时间不匹配。

The following is your code with suggestions, including those specific to clearly applying the same number of calls to free() as to [m][c]alloc() (I chose to use calloc() here to avoid another loop (or memset() ) to initialize memory.)以下是您的代码和建议,包括那些明确应用与[m][c]alloc()相同数量的调用free()的代码(我选择在此处使用calloc()以避免另一个循环(或memset() ) 来初始化 memory。)

Note also, you may need to change the values that this example uses for #defines to meet your needs, but you only need to change them in one place, (at top of file.)另请注意,您可能需要更改此示例用于 #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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM