gpt4 book ai didi

c - 无效的内存读取 - Valgrind

转载 作者:太空宇宙 更新时间:2023-11-04 11:03:18 24 4
gpt4 key购买 nike

我目前正在创建一个 2d 游戏,但为了避免所有的图形和声音开销(我打算使用 allegro 来处理,如果有帮助的话),我正在将其原型(prototype)设计为命令行游戏.

代码按预期工作,目前没有问题。即使当我使用 valgrind 检查是否未检测到内存泄漏时,我也看到没有泄漏是可能的作为 valgrind 状态。
但是,我看到一些行指出 valgrind 检测到 大小为 8 的无效读取 ..这是我以前从未遇到过的问题,最终不知道如何解决。

这是测试代码的示例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_X_GRID (3)
#define MAX_Y_GRID (3)
#define MAX_NUM ((int)(MAX_X_GRID * MAX_Y_GRID))

typedef struct
{
int x;
int y;
} Location;

typedef struct
{
char * description;
char * name;
Location * location;
} Room;

Room *allrooms[MAX_NUM];
int num;

Room *Room_get_at_location(Location locs)
{ /* Get the room at location locs */
Room *r = NULL;
for ( int i = 0; i < MAX_NUM; ++i ) {
r = allrooms[i];
if ((r->location->x == locs.x) && (r->location->y == locs.y))
return r;
}
return NULL;
}

void Room_destroy(Room *room)
{ /* Free Room memory */
free(room->description);
free(room->name);
free(room->location);
free(room);
}

void free_allrooms()
{ /* Destroy all rooms */
Room *r;
for(int x = 1; x <= MAX_X_GRID; ++x)
for(int y = 1; y <= MAX_Y_GRID; ++y)
if ((r = Room_get_at_location((Location){x, y})) != NULL)
Room_destroy(r);
num = 0;
}

Room *Room_create(char *name, char *desc, Location locs)
{ /* Creates a new room */
if (num == MAX_NUM)
return NULL;
Room *r = malloc(sizeof(Room));
r->description = strdup(desc);
r->name = strdup(name);
r->location = malloc(sizeof(Location));
r->location->x = locs.x;
r->location->y = locs.y;
allrooms[num++] = r;
return r;
}

int main(int argc, char const *argv[])
{
num = 0;

Room *r;
for(int x = 1; x <= MAX_X_GRID; ++x) {
for (int y = 1; y <= MAX_Y_GRID; ++y) {
r = Room_create("Main Hall", "Gee, that's the Main Hall .. !", (Location){x, y});
printf("==========\t%s\t[%d, %d]\t==========\n %s\n", r->name, r->location->x, r->location->y, r->description);
}
}
free_allrooms();
return 0;
}

.. 这是 valgrind 报告

==6137== Memcheck, a memory error detector
==6137== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6137== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==6137== Command: ./Main
==6137==
==6137== Invalid read of size 8
==6137== at 0x400604: Room_get_at_location (Main.c:30)
==6137== by 0x4006B4: free_allrooms (Main.c:49)
==6137== by 0x40084A: main (Main.c:79)
==6137== Address 0x51d9050 is 16 bytes inside a block of size 24 free'd
==6137== at 0x4C2B200: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6137== by 0x400680: Room_destroy (Main.c:41)
==6137== by 0x4006CB: free_allrooms (Main.c:50)
==6137== by 0x40084A: main (Main.c:79)
==6137==
==6137== Invalid read of size 4
==6137== at 0x400608: Room_get_at_location (Main.c:30)
==6137== by 0x4006B4: free_allrooms (Main.c:49)
==6137== by 0x40084A: main (Main.c:79)
==6137== Address 0x51d9150 is 0 bytes inside a block of size 8 free'd
==6137== at 0x4C2B200: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6137== by 0x400674: Room_destroy (Main.c:40)
==6137== by 0x4006CB: free_allrooms (Main.c:50)
==6137== by 0x40084A: main (Main.c:79)
==6137==
==6137== Invalid read of size 8
==6137== at 0x400615: Room_get_at_location (Main.c:30)
==6137== by 0x4006B4: free_allrooms (Main.c:49)
==6137== by 0x40084A: main (Main.c:79)
==6137== Address 0x51d9050 is 16 bytes inside a block of size 24 free'd
==6137== at 0x4C2B200: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6137== by 0x400680: Room_destroy (Main.c:41)
==6137== by 0x4006CB: free_allrooms (Main.c:50)
==6137== by 0x40084A: main (Main.c:79)
==6137==
==6137== Invalid read of size 4
==6137== at 0x400619: Room_get_at_location (Main.c:30)
==6137== by 0x4006B4: free_allrooms (Main.c:49)
==6137== by 0x40084A: main (Main.c:79)
==6137== Address 0x51d9154 is 4 bytes inside a block of size 8 free'd
==6137== at 0x4C2B200: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6137== by 0x400674: Room_destroy (Main.c:40)
==6137== by 0x4006CB: free_allrooms (Main.c:50)
==6137== by 0x40084A: main (Main.c:79)
==6137==
========== Main Hall [1, 1] ==========
Gee, that's the Main Hall .. !
========== Main Hall [1, 2] ==========
Gee, that's the Main Hall .. !
========== Main Hall [1, 3] ==========
Gee, that's the Main Hall .. !
========== Main Hall [2, 1] ==========
Gee, that's the Main Hall .. !
========== Main Hall [2, 2] ==========
Gee, that's the Main Hall .. !
========== Main Hall [2, 3] ==========
Gee, that's the Main Hall .. !
========== Main Hall [3, 1] ==========
Gee, that's the Main Hall .. !
========== Main Hall [3, 2] ==========
Gee, that's the Main Hall .. !
========== Main Hall [3, 3] ==========
Gee, that's the Main Hall .. !
==6137==
==6137== HEAP SUMMARY:
==6137== in use at exit: 0 bytes in 0 blocks
==6137== total heap usage: 36 allocs, 36 frees, 657 bytes allocated
==6137==
==6137== All heap blocks were freed -- no leaks are possible
==6137==
==6137== For counts of detected and suppressed errors, rerun with: -v
==6137== ERROR SUMMARY: 90 errors from 4 contexts (suppressed: 0 from 0)

我做错了什么?

最佳答案

原因:

Room_get_at_location 函数有问题。当您一个一个地释放房间时,有可能在调用 Room_get_at_location 时的某个时刻,一些房间已经被释放。在释放的条目上继续测试 r = allrooms[i] 的字段会产生未定义的行为。

解决方案:

在释放数组 allrooms 后,将 NULL 分配给它(将 Room_get_at_location 的返回值更改为指向指针的指针即可),然后在 Room_get_at_location 中跳过它们:

Room *Room_get_at_location(Location locs)
{ /* Get the room at location locs */
Room *r = NULL;
for ( int i = 0; i < MAX_NUM; ++i ) {
r = allrooms[i];
if (!r)
continue;
if ((r->location->x == locs.x) && (r->location->y == locs.y))
return r;
}
return NULL;
}

编辑:

我已经按照上面的解决方案编辑了代码,这次valgrind没有报错。

编辑后的代码如下。请注意这只是为了测试,我确实认为这个修复看起来很难看。您绝对可以重新设计它。

#define _POSIX_C_SOURCE 201401L
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_X_GRID (3)
#define MAX_Y_GRID (3)
#define MAX_NUM ((int)(MAX_X_GRID * MAX_Y_GRID))

typedef struct
{
int x;
int y;
} Location;

typedef struct
{
char * description;
char * name;
Location * location;
} Room;

Room *allrooms[MAX_NUM];
int num;

Room **Room_get_at_location(Location locs)
{ /* Get the room at location locs */
Room **r = NULL;
for ( int i = 0; i < MAX_NUM; ++i ) {
r = &allrooms[i];
if (!*r)
continue;
if (((*r)->location->x == locs.x) && ((*r)->location->y == locs.y))
return r;
}
return NULL;
}

void Room_destroy(Room *room)
{ /* Free Room memory */
free(room->description);
free(room->name);
free(room->location);
free(room);
}

void free_allrooms()
{ /* Destroy all rooms */
Room **r;
for(int x = 1; x <= MAX_X_GRID; ++x)
for(int y = 1; y <= MAX_Y_GRID; ++y)
{
r = Room_get_at_location((Location){x, y});
if (*r)
{
Room_destroy(*r);
*r = NULL;
}
}
num = 0;
}

Room *Room_create(char *name, char *desc, Location locs)
{ /* Creates a new room */
if (num == MAX_NUM)
return NULL;
Room *r = malloc(sizeof(Room));
r->description = strdup(desc);
r->name = strdup(name);
r->location = malloc(sizeof(Location));
r->location->x = locs.x;
r->location->y = locs.y;
allrooms[num++] = r;
return r;
}

int main(int argc, char const *argv[])
{
num = 0;

Room *r;
for(int x = 1; x <= MAX_X_GRID; ++x) {
for (int y = 1; y <= MAX_Y_GRID; ++y) {
r = Room_create("Main Hall", "Gee, that's the Main Hall .. !", (Location){x, y});
printf("==========\t%s\t[%d, %d]\t==========\n %s\n", r->name, r->location->x, r->location->y, r->description);
}
}
free_allrooms();
return 0;
}

结果:

[pengyu@GLaDOS tmp]$ gcc a.c -std=c11 -Wall -ggdb
[pengyu@GLaDOS tmp]$ valgrind ./a.out
==20749== Memcheck, a memory error detector
==20749== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==20749== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==20749== Command: ./a.out
==20749==
========== Main Hall [1, 1] ==========
Gee, that's the Main Hall .. !
========== Main Hall [1, 2] ==========
Gee, that's the Main Hall .. !
========== Main Hall [1, 3] ==========
Gee, that's the Main Hall .. !
========== Main Hall [2, 1] ==========
Gee, that's the Main Hall .. !
========== Main Hall [2, 2] ==========
Gee, that's the Main Hall .. !
========== Main Hall [2, 3] ==========
Gee, that's the Main Hall .. !
========== Main Hall [3, 1] ==========
Gee, that's the Main Hall .. !
========== Main Hall [3, 2] ==========
Gee, that's the Main Hall .. !
========== Main Hall [3, 3] ==========
Gee, that's the Main Hall .. !
==20749==
==20749== HEAP SUMMARY:
==20749== in use at exit: 0 bytes in 0 blocks
==20749== total heap usage: 36 allocs, 36 frees, 657 bytes allocated
==20749==
==20749== All heap blocks were freed -- no leaks are possible
==20749==
==20749== For counts of detected and suppressed errors, rerun with: -v
==20749== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

关于c - 无效的内存读取 - Valgrind,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26192257/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com