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

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

4 回答 4

3

阅读文档

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

realloc如果不对返回值做一些事情,就无法正确使用。现在,您的代码期望realloc始终能够以新块位于同一位置的方式重新分配内存。这显然是不可能的;阵列之后的内存可能正在用于其他用途。

于 2010-12-27T16:08:30.860 回答
3

您使用realloc.

  1. 您将错误的指针传递给realloc. 您应该传递您从中选择的指针malloc,即*bubblesMatrix.
  2. allocBubblesMatrixresizeBubblesMatrix函数中矩阵的“布局”是不同的。在 alloc 函数中,您分配了几个独立的内存块,但在 resize 函数中,您将其视为一大块内存。那根本行不通。

正确的用法是:

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为负数,则 resize 函数中存在内存泄漏。
于 2010-12-27T16:55:57.140 回答
2

我整理了一个快速测试用例,得出的结论是,您现在遇到的问题不在此代码块中。我创建了一个非常简单的测试用例,用整数替换了 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;
  }
}

我所做的唯一更改是将 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 回答