动态多维数组重新分配

发布于 2024-10-09 07:39:37 字数 2823 浏览 0 评论 0原文

我在使用 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 一起使用来获取更多线索。 Windows 上有用的(并且可以快速学习/使用)内存损坏/泄漏检测工具是什么? Purify 是最好的解决方案吗?
  4. 即使我释放数组的函数也会返回页面错误。

I'm having some trouble with the realloc function.

I'm allocating a dynamic bidimensional array with this function:

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

wich is called with the next code:

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

This successfuly creates a bidimensional array 1* MATRIX_X_SIZE.

Then, I want to add a row or multiple rows to the matrix, so I use realloc with the following function. It's supposed to add heightIncrement rows. The problem is that sometimes it works, other it crashes de program.

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

This function is called with:

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

What am I doing wrong?

Function to deallocate the memory blocks previously allocated:

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

Thanks in advance.

EDIT

  1. Silly me. I wasn't doing anything with the return value of realloc as the Karl Knechtel pointed out. But now the program crashes whenever I run it.
  2. With Bart van Ingen Schenau's answer, I confirmed what I feared: I was ignoring the several independent memory blocks that I had allocated previously. I even ended up with a similar code to the one written by Bart but it continues to crash the program.
  3. I've added the assert's to check the results of the malloc/realloc calls and yet I didn't have any luck. I'm using djgpp with Win98 and what's happening it's really odd:
    • Windows: Sometimes, it never crashes; others, it crashes after adding 2 rows.
    • MS-DOS: Crashes after adding 2 rows.
      I'm gonna try to use -O3 with gcc to get additional clues. What would be a useful (and quick to learn/use) memory corruption/leak detection tool for windows? Is Purify the best solution?
  4. Even my function to free the array is returning page faults.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

吃不饱 2024-10-16 07:39:37

阅读文档

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

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

Read the documentation:

The function may move the memory block to a new location, in which case the new location is returned.... A pointer to the reallocated memory block, which may be either the same as the ptr argument or a new location.
The type of this pointer is void*, which can be cast to the desired type of data pointer in order to be dereferenceable.
If the function failed to allocate the requested block of memory, a NULL pointer is returned, and the memory block pointed to by argument ptr is left unchanged.

You cannot correctly use realloc without doing something with the return value. Your code, right now, expects that realloc will always be able to reallocate the memory in such a way that the new block is in the same place. This is clearly impossible; the memory immediately after your array might be in use for something else.

赠意 2024-10-16 07:39:37

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

但是这个函数仍然存在一些问题:

  • mallocrealloc都可能失败,这里没有考虑到
  • 如果heightIncrement > 为负数,则调整大小函数中存在内存泄漏。

There are a number of things wrong with your use of realloc.

  1. You are passing the wrong pointer to realloc. You should pass the pointer you optained from malloc, which would be *bubblesMatrix.
  2. The 'layout' of the matrices in your allocBubblesMatrix and resizeBubblesMatrix functions is different. In the alloc function, you allocate several independent memory blocks, but in the resize function, you treat it as one big block of memory. That will simply not work.

The correct usage would be:

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

But this function still has some issues:

  • Both malloc and realloc can fail, which is not taken into account here
  • If heightIncrement is negative, you have a memory leak in the resize function.
浊酒尽余欢 2024-10-16 07:39:37

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

I threw together a quick test case, and I have come to the conclusion that the problem you are now experiencing is not in this block of code. I created a very simple test case that replaces the Bubble objects with ints. When I do this, the reallocation completes successfully without crashing. Here is my code:

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

The only changes I made were to replace Bubble with int, and to point all the entries in the matrix to a single int variable rather than doing even more allocation.

That means the error is either in drawBubblesMatrix() or in newBubble().

如若梦似彩虹 2024-10-16 07:39:37

您需要单独重新分配每个维度。您无法同时重新分配两个维度,因为每个“行”都是单独分配的。

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

需要更改为

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

You need to reallocated each dimension separately. You cannot reallocate both dimensions at once, since each "row" was allocated individually.

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

needs to change to

*bubblesMatrix = (Bubble ***) realloc(*bubblesMatrix, (height + heightIncrement) * sizeof(Bubble**));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文