2011-10-10 66 views
3

我覺得我有一段代碼會導致內存泄漏。我有一個包含兩個二維數組的數據結構,一個包含ints,另一個包含指向動態分配對象(sprites)的指針。數據結構是一個tilemap,ints是每個位置的數字索引,它們是從文件中讀取的。我把這個索引稱爲「瓷磚」。這告訴了它是什麼類型的瓷磚,用於行爲目的(即玩家對水的反應不同於灰塵或冰)。對象是在各自位置繪製的精靈。該索引被稱爲「圖像」。該索引告訴地圖在該位置繪製哪個精靈。C-可能的內存泄漏?

typedef struct 
{ 
    int** tiles; 
    sprite*** images; 
    int w, h; 
} tilemap; 

我有一個函數可以創建一個新的tilemap,初始化它並返回它。

tilemap* new_tilemap(int w, int h, const char* filename) 
{ 
    tilemap* tm = malloc(sizeof(tilemap)); 
    tm->w = w; 
    tm->h = h; 

    /*allocate memory space for the tiles index*/ 
    tm->tiles = malloc(sizeof(int) * h); 
    int i, j; 
    for (i = 0; i < h; ++i) 
    { 
     tm->tiles[i] = malloc(sizeof(int) * w); 
    } 

    /*fill the index with the appropriate data from a file*/ 
    FILE* file = fopen (filename, "rb"); 
    if (file == NULL) 
    { 
     printf("Failed to open map %s\n", filename); 
    } 

    for (j = 0; j < h; ++j) 
    { 
     for (i = 0; i < w; ++i) 
     { 
      fscanf(file, "%d", &(tm->tiles[j][i])); 
     } 
    } 
    fclose(file); 

    /*allocate space for the images*/ 
    tm->images = malloc(sizeof(sprite*) * h); 
    for (i = 0; i < h; ++i) 
    { 
     tm->images[i] = malloc(sizeof(sprite*) * w); 
    } 

    /*load images based on what type of tile is at that position*/ 
    for (j = 0; j < h; ++j) 
    { 
     for (i = 0; i < w; ++i) 
     { 
      switch (tm->tiles[j][i]) 
      { 
       case 0: 
       tm->images[j][i] = new_sprite_file("dat/tiles/0.bmp", 1); 
       break; 
       case 1: 
       tm->images[j][i] = new_sprite_file("dat/tiles/1.bmp", 2); 
       break; 
      } 
      tm->images[j][i]->x = i*tm->images[j][i]->w; 
      tm->images[j][i]->y = j*tm->images[j][i]->h; 
     } 
    } 
    return tm; 
} 

然後,以釋放tilemap的和所有它的結構,我有這樣的功能:

void free_tilemap(tilemap* tm) 
{ 
    /*loop through and free each of the images in the array*/ 
    int i, j; 
    for (j = 0; j < tm->h; ++j) 
    { 
     for (i = 0; i < tm->w; ++i) 
     { 
      free(tm->images[j][i]); 
     } 
    } 
    /*free the actual array*/ 
    free(tm->images); 
    /*free the tile array?*/ 
    free(tm->tiles); 
    /*free the entire tilemap structure*/ 
    free(tm); 
} 

不過,我覺得這是不釋放所有我已經分配的內存,因爲我用malloc兩次在瓷磚上,但只釋放一次。我不知道這是否是一個問題,雖然看起來像是整數,但我認爲我可能需要循環訪問tiles數組,釋放每一行,然後循環並釋放每列(包含行),與分配方式相同。那是需要做什麼還是我只是無知和/或偏執?與圖像數組相同。此外,隨時指出我的代碼中的其他缺陷,因爲我知道我不是最好的程序員。

+2

你的一些malloc類型是錯誤的。 'tiles'應該是'malloc(sizeof(int *)* N)','images'應該是'malloc(sizeof(sprite **)* M)'等。 –

+2

您是否考慮過使用內存分析工具valgrind在Linux上或淨化在Windows上? –

+0

@KerrekSB你是什麼意思? – Keelx

回答

3

當然,你應該在鏡像空間中看到malloc

for (i = 0; i < h; ++i) 
{ 
    tm->tiles[i] = malloc(sizeof(int) * w); 
} 

/* Inside free_tilemap. */ 
for (i = 0; i < h; ++i) 
{ 
    free(tm->tiles[i]); 
} 
free(tm->tiles); 

同去的其他for s表示酷似這一個。釋放只是tiles不會自動釋放tiles[0..h]級聯。

+0

謝謝。好的解釋也一樣。圖像數組雖然呢? – Keelx

+0

@Keelx'tm-> images [i] = malloc(sizeof(sprite *)* w)''讓我想起'free(tm-> images [i])''。 – cnicutar

+0

這就是我的想法。謝謝! – Keelx

2

快速查看代碼我會說,你確實錯過了瓷磚上的免費。我會建議使用內存分析器來找出你自己。例如。 http://www.cprogramming.com/debugging/valgrind.html 這會給你一個很好的概述分配的內存,以及程序退出時可能的內存泄漏。

+0

非常感謝,它似乎是這樣的事情非常有用的工具。 – Keelx