1

機能に問題がありreallocます。

この関数を使用して、動的な二次元配列を割り当てています。

Bubble ***allocBubblesMatrix(int height, int width) {
  Bubble ***bubblesMatrix = (Bubble***) malloc(height * sizeof(Bubble**));
  assert(bubblesMatrix != NULL);
  int i;
  for (i = 0; i < height; ++i) {
    bubblesMatrix[i] = (Bubble**) malloc(width * sizeof(Bubble*));
    assert(bubblesMatrix[i] != NULL);
  }
  int x, y;  
  for (y = 0; y < height; ++y)
    for (x = 0; x < width;  ++x)
      bubblesMatrix[y][x] = newBubble(rand() % N_BUBBLES);

  return bubblesMatrix;
}

次のコードで呼び出されます。

int matrixHeight = 1, 
    matrixWidth  = MATRIX_X_SIZE;
Bubble ***bubblesMatrix = allocBubblesMatrix(matrixHeight, matrixWidth);

これにより、2 次元配列 1* MATRIX_X_SIZE が正常に作成されます。

次に、行列に行または複数の行を追加したいのでrealloc、次の関数で使用します。heightIncrement行を追加することになっています。問題は、動作することもあれば、プログラムがクラッシュすることもあります。

void resizeBubblesMatrix(Bubble ****bubblesMatrix, int height, int width, 
                         int heightIncrement) {
  if (heightIncrement <= 0) /* temporary */
    return;

  *bubblesMatrix = (Bubble***) realloc(*bubblesMatrix, (height + heightIncrement) * sizeof(Bubble**));
  assert(bubblesMatrix != NULL);
  int x, y;
  int newHeight = height + heightIncrement;

  for (y = height; y < newHeight; ++y) {
    (*bubblesMatrix)[y] = (Bubble**) malloc(width * sizeof(Bubble*));
    assert((*bubblesMatrix)[y] != NULL);
    for (x = 0; x < width; ++x)
      (*bubblesMatrix)[y][x] = newBubble(rand() % N_BUBBLES);
  }
}

この関数は次のように呼び出されます。

while(true) {
  drawBubblesMatrix(x1, y1, matrixHeight, matrixWidth, &bubblesMatrix, bubbles);
  resizeBubblesMatrix(&bubblesMatrix, matrixHeight, matrixWidth, 1);
  ++matrixHeight;
  getch();
  clear_screen(1);
}

私は何を間違っていますか?

以前に割り当てられたメモリ ブロックの割り当てを解除する関数:

void freeBubblesMatrix(Bubble ****bubblesMatrix, int height, int width) {
  int y, x;
  for (y = 0; y < height; ++y) {
    for (x = 0; x < width; ++x) {
      free((*bubblesMatrix)[y][x]);
      (*bubblesMatrix)[y][x] = NULL;
    }
    free((*bubblesMatrix)[y]);
    (*bubblesMatrix)[y] = NULL;
  }
  free(*bubblesMatrix);
  *bubblesMatrix = NULL;
}

前もって感謝します。

編集

  1. 愚かな私。reallocKarl Knechtel が指摘したように、私は の戻り値で何もしていませんでした。しかし、今では実行するたびにプログラムがクラッシュします。
  2. Bart van Ingen Schenau の回答で、私が恐れていたことを確認しました。以前に割り当てたいくつかの独立したメモリ ブロックを無視していたのです。Bart によって書かれたものと同様のコードになってしまいましたが、引き続きプログラムをクラッシュさせます。
  3. /呼び出しassertの結果を確認するために 's を追加しましたが、うまくいきませんでした。私は Win98 で djgpp を使用していますが、何が起こっているのかは本当に奇妙です: mallocrealloc
    • Windows: クラッシュしないこともあります。それ以外では、2 行追加するとクラッシュします。
    • MS-DOS: 2 行を追加するとクラッシュします。追加の手がかりを得るために、gcc で -O3 を使用してみます。Windows 用の便利な (そしてすぐに習得/使用できる) メモリ破損/リーク検出ツールは何でしょうか? Purify は最適なソリューションですか?
  4. 配列を解放する関数でさえ、ページ フォールトを返しています。
4

4 に答える 4

3

ドキュメントを読む:

この関数は、メモリ ブロックを新しい場所に移動する場合があります。その場合、新しい場所が返されます.... 再割り当てされたメモリ ブロックへのポインタ。これは、ptr 引数と同じか、新しい場所のいずれかです。このポインターの型は void* であり、逆参照可能にするために目的の型のデータ ポインターにキャストできます。関数が要求されたメモリ ブロックの割り当てに失敗した場合、NULL ポインタが返され、引数 ptr が指すメモリ ブロックは変更されません。

realloc戻り値を何とかしないと正しく使えません。あなたのコードは、現在、realloc新しいブロックが同じ場所にあるように常にメモリを再割り当てできることを期待しています。これは明らかに不可能です。配列の直後のメモリは、他の目的で使用されている可能性があります。

于 2010-12-27T16:08:30.860 に答える
3

の使用には多くの問題がありますrealloc

  1. に間違ったポインタを渡していますrealloc。から取得したポインタを渡す必要があります。mallocこれは になります*bubblesMatrix
  2. allocBubblesMatrix関数と関数の行列の「レイアウト」resizeBubblesMatrixが異なります。alloc 関数では、いくつかの独立したメモリ ブロックを割り当てますが、resize 関数では、それを 1 つの大きなメモリ ブロックとして扱います。それは単にうまくいきません。

正しい使い方は次のとおりです。

void resizeBubblesMatrix(Bubble ****bubblesMatrix, int height, int width, 
                         int heightIncrement) {
  *bubblesMatrix = (Bubble ***) realloc(*bubblesMatrix, (height + heightIncrement) * sizeof(Bubble**));
  int i;
  int newHeight = height + heightIncrement;
  for (i = height; i < newHeight; ++i)
    (*bubblesMatrix)[i] = (Bubble**) malloc(width * sizeof(Bubble*));
  int x, y;
  for (y = height; y < newHeight; ++y)
    for (x = 0; x < width; ++x)
      (*bubblesMatrix)[y][x] = newBubble(rand() % N_BUBBLES);
}

しかし、この関数にはまだいくつかの問題があります。

  • との両方が失敗する可能性がmallocありreallocますが、ここでは考慮されていません
  • が負の場合heightIncrement、サイズ変更関数でメモリ リークが発生しています。
于 2010-12-27T16:55:57.140 に答える
2

簡単なテスト ケースを作成しましたが、現在発生している問題はこのコード ブロックにはないという結論に達しました。Bubble オブジェクトを int に置き換える非常に単純なテスト ケースを作成しました。これを行うと、再割り当てはクラッシュすることなく正常に完了します。これが私のコードです:

#include <malloc.h>
#include <assert.h>

int myVal = 0xDEAD;

int ***allocBubblesMatrix(int height, int width);
void resizeBubblesMatrix(int ****bubblesMatrix, int height, int width, 
                         int heightIncrement);

int main(int argc, char **argv)
{
  int matrixHeight = 1, matrixWidth = 10;
  int i = 0;
  int ***matrix = allocBubblesMatrix(matrixHeight, matrixWidth);
  for(i = 1; i < matrixWidth; i++)
    resizeBubblesMatrix(&matrix, matrixHeight, matrixWidth, 1);
  printf("Complete!\n");
}

int ***allocBubblesMatrix(int height, int width) {
  int ***bubblesMatrix = (int***) malloc(height * sizeof(int**));
  assert(bubblesMatrix != NULL);
  int i;
  for (i = 0; i < height; ++i) {
    bubblesMatrix[i] = (int**) malloc(width * sizeof(int*));
    assert(bubblesMatrix[i] != NULL);
  }
  int x, y;  
  for (y = 0; y < height; ++y)
    for (x = 0; x < width;  ++x)
      bubblesMatrix[y][x] = &myVal;

  return bubblesMatrix;
}

void resizeBubblesMatrix(int ****bubblesMatrix, int height, int width, 
                         int heightIncrement) {
  if (heightIncrement <= 0) /* temporary */
    return;

  *bubblesMatrix = (int***) realloc(*bubblesMatrix, (height + heightIncrement) * sizeof(int**));
  assert(bubblesMatrix != NULL);
  int x, y;
  int newHeight = height + heightIncrement;

  for (y = height; y < newHeight; ++y) {
    (*bubblesMatrix)[y] = (int**) malloc(width * sizeof(int*));
    assert((*bubblesMatrix)[y] != NULL);
    for (x = 0; x < width; ++x)
      (*bubblesMatrix)[y][x] = &myVal;
  }
}

私が行った唯一の変更は、Bubble を int に置き換え、さらに多くの割り当てを行うのではなく、マトリックス内のすべてのエントリを単一の int 変数にポイントすることでした。

これは、エラーが drawBubblesMatrix() または newBubble() のいずれかにあることを意味します。

于 2010-12-30T03:10:29.830 に答える
1

各次元を個別に再割り当てする必要があります。各「行」は個別に割り当てられているため、両方のディメンションを一度に再割り当てすることはできません。

*bubblesMatrix = (Bubble ***) realloc(bubblesMatrix, (height + heightIncrement) * width * sizeof(Bubble*));

に変更する必要があります

*bubblesMatrix = (Bubble ***) realloc(*bubblesMatrix, (height + heightIncrement) * sizeof(Bubble**));
于 2010-12-27T17:01:22.303 に答える