2017-04-06 5 views
1

学校では、マップをセルで初期化する必要があります。 Valgrindでコードを分析しているときに、いくつかの問題が発生しました。 私が使用した初期化関数は、以前に動作しましたが、2つの追加の整数ポインタと整数を追加した後に機能しなくなりました。メモリは動的に割り振られていて、以前にも存在していた部分にバグが現れます。発生したエラーは以下の通りであった:構造体コードを追加した後、Valgrindが無効になります。

worldmap* initialize_map(game_settings* settings) 
{ 
    int maxplayers = 10; 
    int rows = settings->rows; 
    int cols = settings->cols; 
    worldmap* world = malloc(sizeof(worldmap)); //free in cleanup_map 
    if(world != NULL) 
    { 
     world->rows = rows; 
     world->cols = cols; 
     world->map = malloc(sizeof(cell)*rows*cols); //free in cleanup_map 
     for(int i = 0; i < rows;i++) 
     { 
      for(int j = 0; j < cols;j++) 
      { 
      cell* cell = index_map(world, j, i); //cell* is world->map + offset 
      cell->type = CELL_DIRT; 
      cell->owner = 0; 
      } 
     } 
     world->players = 0; 
     world->score = NULL; //NULL pointer, since this pointer set in a later function 
     world->playerturns = NULL; //NULL pointer, since this pointer set in a later function 
     return world; 
    } 
    else{printf("No world found.\n");} 
} 

このinitialize_map()コードへの追加は、次のとおりです:int maxplayersworld->playersworld->scoreworld->playerturns、残りのコード

==4877== Invalid write of size 4 
==4877== at 0x401723: initialize_map (list.c:312) 
==4877== by 0x400B99: main (initialization.c:14) 
==4877== Address 0x550deb8 is 0 bytes after a block of size 2,584 alloc'd 
==4877== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4877== by 0x4016EA: initialize_map (list.c:306) 
==4877== by 0x400B99: main (initialization.c:14) 
==4877== 
==4877== Invalid write of size 4 
==4877== at 0x40172D: initialize_map (list.c:313) 
==4877== by 0x400B99: main (initialization.c:14) 
==4877== Address 0x550debc is 4 bytes after a block of size 2,584 alloc'd 
==4877== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4877== by 0x4016EA: initialize_map (list.c:306) 
==4877== by 0x400B99: main (initialization.c:14) 
==4877== 

valgrind: m_mallocfree.c:277 (mk_plain_bszB): Assertion 'bszB != 0' failed. 
valgrind: This is probably caused by your program erroneously writing past the 
end of a heap block and corrupting heap metadata. If you fix any 
invalid writes reported by Memcheck, this assertion failure will 
probably go away. Please try that before reporting this as a bug. 

初期化コードは以下のとおりです。これらの追加なしで、valgrindで実行するときに有効でした。このコードでindex_map()cell* w->map+y_offset + x_offset

を返します。これは整数値と整数ポインタを別々に割り当てることと関連しているかもしれません(無効な書き込みエラーを出した部分でこれをやろうとしました。 ):

world->map = malloc(sizeof(cell)*rows*cols); 
for(int i = 0; i < rows;i++) 
{ 
    for(int j = 0; j < cols;j++) 
    { 
     cell* cell = index_map(world, j, i); //cell8 is world->map + offset 
     cell->type = malloc(sizeof(celltype); 
     *(cell->type) = CELL_DIRT; 
     cell->owner = malloc(sizeof(int); 
     *(cell->type) = 0; 
    } 
} 

このコードをコンパイルしようとすると、folllowingのエラーが表示されます。

"invalid type argument of unary ‘*’ (have ‘unsigned int’) *(cell->type) = 0; "

これらは、私が使用した構造体です:

セル構造体:

typedef struct{ 
    celltype type; 
    unsigned int owner; 
} cell; 

世界地図の構造体:

typedef struct 
{ 
    cell* map; 
    unsigned int rows; 
    unsigned int cols; 
    int players; 
    int* score; 
    int* playerturns; 
} worldmap; 

セル構造体は変わらず、世界地図の構造体は、以前はcell* mapunsigned int rowsunsigned int colsで構成しました。

EDIT index_mapコード:

cell* index_map(worldmap* w, int x, int y) 
{ 
    cell* place; 
    place = w->map + x*w->cols + y; 
    return place; 
} 
+0

オリジナルのバグのソースであると思われる 'index_map'cosのコードを含めることができますか? –

答えて

0

valgrindエラーは基本的に、割り当てたマップの境界を超えてメモリにアクセスしているということです。そして今、あなたがindex_map関数を含んでいたので、なぜそれも明らかです。

マップが5列×2行の場合、サイズが10セルであるとします。 4および1.あなたの機能は、21セルを返すために、4 * 5 + 1を計算していることが最もxとyは可能性を意味します...それをうまくするためのコードは、この

place = w->map + x*w->rows + y; 

または

する必要があります
place = w->map + x + y*w->cols; 

これは、4 * 2 + 1または4 + 1 * 5 = 9番目のセルを与えます。

あなたが言及した他の問題については、ポインタではないので、それらの値にメモリを割り当てる必要はありません。あなたはそれに値を代入するcell->owner = 10;を行うことができますので、例えば

cell->owner = malloc(sizeof(int); 

cell->ownerはunsigned int型です。

さらに、*(cell->owner)は過剰使用であり、cell->ownerが必要です。

1
  • cell->type = malloc(sizeof(celltype);タイプは、ポインタではありません。 cellのためにmallocしますか? index_maxとは何ですか?
  • cell* cellタイプと変数に同じ名前を使用することは賢明ではありません。
  • *(cell->type)はナンセンスです。 cell->typeまたは(*cell).typeを使用してください(前者は読みやすくなります)。
  • 全体的に、mallocは意味を持たないようなところでいくつかの場所で使用しています。代わりに単純な変数を使用することもできます。
  • ここであなたはfree()ですか?あなたがしなければValgrindが動揺するかもしれません。

など。

関連する問題