动态多维数组重新分配

时间:2010-12-27 16:04:34

标签: c dynamic multidimensional-array memory-management realloc

我在使用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);

这成功地创建了一个二维数组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. 傻傻的我。 Karl Knechtel指出,我没有对realloc的返回值做任何事情。但是现在每当我运行程序时程序都会崩溃。
  2. 在Bart van Ingen Schenau的回答中,我确认了我所担心的:我忽略了之前分配的几个独立内存块。我甚至最终得到了与Bart编写的代码相似的代码,但它继续使程序崩溃。
  3. 我添加了assert来检查malloc / realloc来电的结果,但我没有运气。我正在使用带有Win98的djgpp,它发生了什么真的很奇怪:
    • Windows:有时,它永远不会崩溃;其他人,在添加2行后崩溃。
    • MS-DOS:添加2行后崩溃。 我将尝试使用-O3和gcc来获得更多线索。什么是一个有用的(和快速学习/使用)内存损坏/泄漏检测工具的窗口?净化是最好的解决方案吗?
  4. 即使是我释放数组的函数也会返回页面错误。

4 个答案:

答案 0 :(得分:3)

阅读documentation

  

该函数可以将存储块移动到新位置,在这种情况下返回新位置....指向重新分配的存储块的指针,该指针可以与ptr参数或新位置相同。   此指针的类型为void *,可以将其强制转换为所需类型的数据指针,以便可以取消引用。   如果函数未能分配请求的内存块,则返回NULL指针,并且参数ptr指向的内存块保持不变。

如果不对返回值执行某些操作,则无法正确使用realloc。您的代码现在希望realloc始终能够以新块在同一位置的方式重新分配内存。这显然是不可能的;你的阵列可能正在使用其他东西之后的内存。

答案 1 :(得分:3)

使用realloc时出现了许多问题。

  1. 您将错误的指针传递给realloc。你应该传递你从malloc获得的指针,它将是*bubblesMatrix
  2. allocBubblesMatrixresizeBubblesMatrix函数中矩阵的“布局”不同。在alloc函数中,您分配了几个独立的内存块,但在resize函数中,您将其视为一个大的内存块。这根本行不通。
  3. 正确的用法是:

    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);
    }
    

    但是这个功能仍有一些问题:

    • mallocrealloc都可能失败,此处未予考虑
    • 如果heightIncrement为负数,则调整大小函数中会出现内存泄漏。

答案 2 :(得分:2)

我汇总了一个快速测试用例,我得出的结论是,您现在遇到的问题不在于此代码块。我创建了一个非常简单的测试用例,用int替换Bubble对象。当我这样做时,重新分配成功完成而不会崩溃。这是我的代码:

#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;
  }
}

我所做的唯一更改是用String替换Bubble,并将矩阵中的所有条目指向单个int变量,而不是进行更多的分配。

这意味着错误发生在drawBubblesMatrix()或newBubble()中。

答案 3 :(得分:1)

您需要单独重新分配每个维度。您不能一次重新分配这两个维度,因为每个“行”都是单独分配的。

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

需要改为

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