1

このようなもので作成された2次元配列があるとすると、

char **foo = (char **) malloc(height * sizeof(char *));
for(i = 0; i <= height; i++) 
    foo[i] = (char *) malloc (width * sizeof(char *));

まず第一に、これはこのような配列を作成する正しい方法でさえありますか?ここでの落とし穴は、「高さ」と「幅」は実行時に設定されるものです。

これはうまくいくようですが、これはこの2Dアレイを解放するための最良の戦略です。free(funge)は間違っているように聞こえます。ここにある他のいくつかの投稿を見ていくと、各行を1つずつ無料にすることができると思いますか?

私はこのようなことを試みました、

for (height = 0; height < ip_ptr->funge_height; height++) {
    free(funge[height]);
} 
free(funge)

ただし、これにより、ダブルフリーポインタ例外が発生します。これは、このメモリを管理する必要がないという意味ですか?私は、mallocされたメモリごとに、free()を呼び出す必要があるという印象を受けました。

4

9 に答える 9

8

すべての「行」は同じサイズであるため、1つの急降下で割り当てることができます(の2D配列を作成するのか、malloc(height * width * sizeof (char *))の2D配列を作成するのかは完全には明確ではありません)。乗算を使用して、適切なインデックスを計算できます(つまり、になります)。charchar *foo[i][j]foo + i * height + j

free()同様に、1回の呼び出しで応答します。

于 2009-10-14T18:19:28.233 に答える
8

割り当てのforループで、のi <= height;代わりに使用していますi < height;。したがって、無効なメモリ位置に書き込んでいると、コードの動作が予測できなくなります。

于 2009-10-14T18:20:46.803 に答える
7

2番目の割り当ては次のようになります。

foo[i] = (char *) malloc (width * sizeof(char));

height+1また、割り当て中に時間をループしています。

それに加えて、これらの2つのスニペットは私には正しいように思われるので、エラーは別の場所にあるはずです。

アレイがメモリの1つの大きなチャンクとして割り当てられた場合は、一度だけ解放する必要があります。

char **foo = (char **) malloc(height * sizeof(char *));
*foo = malloc(height * width * sizeof(char))
for (int i = 1; i < height; i++) {
  foo[i] = *foo + i*width;
}
//and you just do 2 frees
free(*foo);
free(foo);
于 2009-10-14T18:22:36.017 に答える
3

幅と高さが実行時の値である場合、割り当てるメカニズムは問題ありません(ただし、割り当てループではsizeof(char)なく使用する必要があります。文字列を全体的に割り当てます)。sizeof(char *)

各malloc()に対して1回free()を呼び出す必要があるというあなたの印象は基本的に正しいです(calloc()やrealloc()のようなものは単純な話を複雑にします)。

ループの後にfreeが続くのは正しいはずです(または、少なくとも、最初にサブ配列を解放し、次にサブ配列へのポインタの配列を解放するという一般的なメカニズム)-したがって、ダブルフリーエラーがどこから来ているのかを確認する必要があります。ip_ptr->funge_heightどこで制御されたかはわかりません。fungeで記述されていることはすぐにはわかりませんip_ptr->funge_height


'unknown@google'の回答を参照してください-配列の境界の問題があります。

于 2009-10-14T18:19:50.593 に答える
2

メモリを割り当てるときはi < height、ループ条件として使用する必要があります。

メモリの割り当てを解除するときは、割り当てたときと同じインデックスまで繰り返す必要があります。 ip_ptr->funge_heightオリジナルと同じである必要がありますが、height明らかにそうではありません。

それ以外は、動作するはずです。

これは別の方法です。これには、mallocとfreeの数が少なくなります。

割り当てるには:

char **foo = malloc (height * sizeof (char **));
foo[0] = malloc (height * width * sizeof (char *));
for (i = 1;  i < height;  ++i) {
    foo[i] = foo[i-1] + width;
}

割り当てを解除するには:

free (foo[0]);
free (foo);
于 2009-10-14T18:21:48.663 に答える
0

コンパイラがそれをサポートしている場合は、可変長配列へのポインタを使用できます。

size_t width = 10, height = 5;
char *(*foo)[height][width] = malloc(sizeof *foo);

配列要素にアクセスする前に、ポインタの参照を解除する必要があることに注意してください。

(*foo)[1][2] = "foo";

これには、単一の呼び出しfoで割り当てを解除できる、単一の連続したメモリブロックのみを割り当てるという利点がありますfree()

于 2009-10-14T18:51:21.443 に答える
0

割り当て(高さ>0および幅>0と仮定)

char **foo, *row;

assert(height > 0 && width > 0);
foo = malloc(height * sizeof *foo);
row = malloc(height * width * sizeof *row);
assert(foo != NULL && row != NULL);

for (i = 0; i < height; ++i, row += width) 
  foo[i] = row;

assert(row == *foo + height * width);

割り当て解除

assert(foo != NULL);
free(*foo);
free(foo);
于 2009-10-14T18:28:33.160 に答える
0

このような場合、いつでもvalgrindを使用できます。実行可能ファイルをコンパイルして実行するだけです。

valgrind --leak-check=full ./a.out

Valgrindはすべてのメモリ検証を検出し、関連するコード行を指し示します。

あなたの場合、インデックス作成の問題(<vs. <=)を簡単に見つけることができたかもしれません。

于 2009-10-14T18:33:49.857 に答える
0

この100%は、exeファイルがクラッシュすることなく機能します。

char **map2d;
map2d=(char **)malloc(MAXY*sizeof(char *));
for(int a=0; a<MAXY; a++)
    map2d[a]=(char *)malloc(MAXX*sizeof(char));
for(int a=0; a<MAXX; a++)
    free(map2d[a]);
free(map2d);
于 2014-02-02T19:25:03.240 に答える