簡體   English   中英

無效的內存讀取-Valgrind

[英]Invalid memory read - Valgrind

目前,我正在創建2D游戲,但是為了避免所有圖形和聲音開銷(如果有幫助,我打算使用allegro進行處理),因此將其作為命令行游戲進行原型制作。

該代碼按預期工作,到目前為止沒有問題。 即使當我使用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]測試字段會生成未定義的行為。

解:

將其釋放后,將NULL分配給數組allrooms的條目(更改指針的Room_get_at_location的返回值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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM