动态多维数组重新分配
我在使用 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;
}
提前致谢。
编辑
- 我真傻。正如 Karl Knechtel 指出的那样,我没有对 realloc 的返回值做任何事情。但现在每当我运行该程序时就会崩溃。
- 根据 Bart van Ingen Schenau 的回答,我证实了我所担心的事情:我忽略了之前分配的几个独立内存块。我什至最终得到了与 Bart 编写的代码类似的代码,但它仍然使程序崩溃。
- 我添加了
assert
来检查malloc
/realloc
调用的结果,但我没有任何运气。我在 Win98 中使用 djgpp,发生的事情真的很奇怪:- Windows:有时,它永远不会崩溃;其他人,添加 2 行后崩溃。
- MS-DOS:添加 2 行后崩溃。 我将尝试将 -O3 与 gcc 一起使用来获取更多线索。 Windows 上有用的(并且可以快速学习/使用)内存损坏/泄漏检测工具是什么? Purify 是最好的解决方案吗?
- 即使我释放数组的函数也会返回页面错误。
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
- 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. - 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.
- I've added the
assert
's to check the results of themalloc
/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?
- Even my function to free the array is returning page faults.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
阅读文档:
如果不对返回值执行某些操作,则无法正确使用
realloc
。现在,您的代码期望realloc
始终能够以新块位于同一位置的方式重新分配内存。这显然是不可能的;数组后面的内存可能正在用于其他用途。Read the documentation:
You cannot correctly use
realloc
without doing something with the return value. Your code, right now, expects thatrealloc
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.使用
realloc
时存在很多问题。realloc
传递了错误的指针。您应该传递从malloc
获得的指针,该指针为*bubblesMatrix
。allocBubblesMatrix
和resizeBubblesMatrix
函数中矩阵的“布局”不同。在alloc函数中,您分配了几个独立的内存块,但在resize函数中,您将其视为一大块内存。那根本行不通。正确的用法是:
但是这个函数仍然存在一些问题:
malloc
和realloc
都可能失败,这里没有考虑到heightIncrement
> 为负数,则调整大小函数中存在内存泄漏。There are a number of things wrong with your use of
realloc
.realloc
. You should pass the pointer you optained frommalloc
, which would be*bubblesMatrix
.allocBubblesMatrix
andresizeBubblesMatrix
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:
But this function still has some issues:
malloc
andrealloc
can fail, which is not taken into account hereheightIncrement
is negative, you have a memory leak in the resize function.我整理了一个快速测试用例,得出的结论是您现在遇到的问题不在这段代码中。我创建了一个非常简单的测试用例,用整数替换 Bubble 对象。当我这样做时,重新分配成功完成而不会崩溃。这是我的代码:
我所做的唯一更改是将 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:
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().
您需要单独重新分配每个维度。您无法同时重新分配两个维度,因为每个“行”都是单独分配的。
需要更改为
You need to reallocated each dimension separately. You cannot reallocate both dimensions at once, since each "row" was allocated individually.
needs to change to