第三次重新分配内存时 C 程序崩溃

C program crashes when reallocating memory a third time

提问人:Artiom Kvartiuk 提问时间:10/6/2023 最后编辑:Artiom Kvartiuk 更新时间:10/8/2023 访问量:71

问:

我正在学习 SDL2 以用 c 语言制作一个简单的游戏。我编写了一些代码来将实体存储在一个数组中,这样我就可以遍历它们以呈现和移动它们。每当我按下 R 键时,它都应该发射一颗子弹。它做一次,如果我第二次按 R,窗口就会关闭。代码如下:

typedef struct {
    int x;
    int y;
    int w;
    int h;
    int up;
    int down;
    int left;
    int right;
    SDL_Texture *texture;
} Entity;

typedef struct {
    Entity *entities;
    int size;
    int cap;
} EntityArray;

EntityArray 实体Arr;

void addEntity(Entity *entity)
{
    printf("Inside moveEntity function\n");
    printf("The tmp pointer is %d bytes\n", (entityArr.size+1)*sizeof(entityArr.entities));
    Entity *tmp = (Entity*)realloc(entityArr.entities,(entityArr.size+1)*sizeof(entityArr.entities)); // crashes here whenever I allocate more than 16 bytes
    if(!tmp)
    {
        printf("Could not allocate memory for entity in array");
        free(tmp);
        return;
    }
    entityArr.entities = realloc(entityArr.entities, (entityArr.size+1)*sizeof(entityArr.entities));
    entityArr.size++;
    //memcpy((entityArr.entities+(entityArr.size-1)), entity, sizeof(Entity));
    (*(entityArr.entities+(entityArr.size-1))) = (*entity);
    printf("The entity %d has been added to the array!\n", entityArr.size);
}
int main(int argc, char **argv)
{
    memset(&app, 0, sizeof(App));
    memset(&player, 0, sizeof(Entity));
    //memset(&entityArr, 0, sizeof(EntityArray));

    entityArr.entities = calloc(1, sizeof(Entity*)); 
    entityArr.size = 0;
    entityArr.cap = 0;

    initSDL();

    player.x = 100;
    player.y = 100;
    player.w = 64;
    player.h = 64;
    player.texture = loadTexture("assets/textures/player.png");

    printf("Player entity initialized at address: %p\n", &player);
    
    bullet.x = player.x;
    bullet.y = player.y;
    bullet.w = 16;
    bullet.h = 16;
    bullet.up = 1;
    bullet.texture = loadTexture("assets/textures/bullet.png");
    if(bullet.texture)
    {
        printf("The bullet texture has been defined\n");
    } else {
        printf("The bullet texture has not been defined\n");
    }

    addEntity(&player);


    atexit(cleanUp);

    while (1)
    {
        prepareScene();

        doInput();

        moveEntity(&entityArr.entities);

        blitEntity(entityArr.entities);

        presentScene();

        SDL_Delay(16);
    }

    return 0;
}

每当我尝试重新分配超过 16 个字节时,它都会崩溃

我尝试使用记忆功能,但此时我已经筋疲力尽,不知道自己在做什么

c 内存管理 动态数组

评论

1赞 dbush 10/6/2023
通过 valgrind 运行代码。如果你对内存管理不善,它会告诉你在哪里。
2赞 Fe2O3 10/6/2023
(entityArr.size+1)*sizeof(entityArr.entities)乘以指针的大小,而不是所指向的对象的大小(如预期的那样)。把一个放在那些括号里,一切都会好起来的......*
2赞 Peter - Reinstate Monica 10/6/2023
此外,分配给 tmp 的第一个 realloc 会释放原始内存。第二个 reealloc 试图再次释放它。尝试使用正确的尺寸(只需一次。(entityArr.size+1)*sizeof(Entity)
1赞 Ted Lyngmo 10/6/2023
顺便说一句,什么?我们只看到声明?如果需要调试帮助,请发布可编译的代码。entityArrEntityArray
3赞 Weather Vane 10/6/2023
您已经重新定位了两次,请将第二个替换为 .更好的是entityArr.entities = tmp;Entity *tmp = realloc(... , (entityArr.size+1)*sizeof *tmp);

答:

2赞 ahiddenjem 10/6/2023 #1

在 tmp 中拥有新的内存块后,只需将其分配给实体字段即可。在第一次重新分配成功后,无需进行第二次重新分配。事实上,第二次重新分配现在发生在作为第一次重新分配操作的一部分释放的同一指针上,因此第二次重新分配是错误的。此外,您还需要确定要分配的大小。

void addEntity(Entity *entity)
{
    printf("Inside moveEntity function\n");
    printf("The tmp pointer is %d bytes\n", (entityArr.size+1)*sizeof(Entity));
    Entity *tmp = (Entity*)realloc(entityArr.entities,(entityArr.size+1)*sizeof(Entity)); // crashes here whenever I allocate more than 16 bytes
    if(!tmp)
    {
        printf("Could not allocate memory for entity in array");
        free(tmp);
        return;
    }
    entityArr.entities = tmp;
    entityArr.size++;
    //memcpy((entityArr.entities+(entityArr.size-1)), entity, sizeof(Entity));
    (*(entityArr.entities+(entityArr.size-1))) = (*entity);
    printf("The entity %d has been added to the array!\n", entityArr.size);
}

评论

0赞 ahiddenjem 10/6/2023
在第一次重新分配时,将释放位于 entityArr.entities 处的指针。然后,当他们调用第二个 realloc 时,这现在是一个错误的输入,并在传递给第二个 realloc 时导致错误行为。
0赞 Fe2O3 10/6/2023
只是仔细看了看OP代码。你是正确的,OP应该像你所展示的那样使用。我的错误。但是,指定所需块大小的参数不正确,无论是在 OP 代码中还是在这个答案中......请修复...而且,在 C 语言中,强制转换返回的指针是不必要的(并且在进行修改时可能会导致错误。tmp
0赞 ahiddenjem 10/8/2023
更新了答案。
1赞 Fe2O3 10/8/2023
更好。。。仍在铸造回报......而且,一个好的答案会指出......甚至可以重新排列最后几行,以便增量跟随赋值(不需要......到达那里....慢慢。。。(这些不是代码的问题。这些是简单的好代码与坏代码。malloc()free(tmp);-1