我正在尝试构建一个自我调整大小的堆栈,realloc()
会崩溃我的程序。
构造
Stack::Stack()
{
st = (int*)malloc(sizeof(int));
sp = 0;
length = 1;
}
这是我的add()
功能:
void Stack::add(int item)
{
if (sp == length)
Stack::resizeStack(&st, &length, 1);
st[sp++] = item;
}
调整大小功能(我使用变量a以便能够重复使用它):
void Stack::resizeStack(int **st, int *length, bool a)
{
if (a == 1)
*length *= 2;
else
*length /= 2;
realloc(*st, sizeof(int) * (*length));
}
这就是我测试堆栈的方式:
Stack* myStack = new Stack();
for (int i = 0; i < 10; i += 1) {
myStack->add(i);
cout << myStack->getStackSize() << '\n';
}
free(myStack);
我注意到程序在for
。
如果有人解释我做错了什么,我将不胜感激。
答案 0 :(得分:4)
你很幸运,你遇到了崩溃。这是未定义的行为。
让我们看看Bjarne Stroustrup从here对此发表的看法:
不,从某种意义上说,你无法使用malloc()和 使用删除释放它。你也不能用new分配和删除 free()或对new分配的数组使用realloc()。
C ++运算符new和delete保证了正确的构造和 破坏;需要调用构造函数或析构函数的地方, 他们是。 C风格函数malloc(),calloc(),free()和 realloc()并不能确保这一点。 此外,无法保证 new和delete用于获取和释放原始内存的机制 与malloc()和free()兼容。如果混合风格适用于你的 系统,你现在只是&#34;幸运&#34; 。
C ++ FAQ也有特殊条目:
https://isocpp.org/wiki/faq/freestore-mgmt#realloc-and-renew
答案 1 :(得分:4)
所有那些在C ++中说malloc()
和free()
是个坏主意的人都是100%正确的。首选new
和delete
优先于malloc()
和free()
,而不是您自己的自制堆栈实现上的标准库容器。
无论如何,这里的真正问题是,realloc()
可能会分配一个新的内存块并释放旧的内存块。它返回一个指向新指针的指针。
正确的电话是:
*st = realloc(*st, sizeof(int) * (*length));
现在*st
将存储新指针,一切都很好。
考虑使用标准库,而不是实现自己的基础数据结构。它有一个设计良好的界面,并经过了彻底的测试。
答案 2 :(得分:2)
最终崩溃很可能是因为您将new
与free
混合在一起。这是未定义的行为。它可能适用于某些系统,但绝不是一个好主意。您应该将new
与delete
配对。对malloc
的呼叫与free
配对,但这些更多用于C代码。 C ++代码通常使用new
和delete
。
当然,您可以通过将new
设为局部变量来消除myStack
:
Stack myStack;
您还需要调整成员访问权限才能使用.
而不是->
。没有必要删除myStack,因为一旦函数退出,局部变量将自动清除,包括异常情况。
还注意到realloc
的返回值被忽略。如果当前内存块不能被realloc
扩展,它必须分配一个新的内存块并将旧数据复制到它。在这种情况下会返回一个新指针,因此必须更新st
。
*st = realloc(*st, sizeof(int) * (*length));
但是,再次使用malloc
,realloc
和free
在C ++代码中有点奇怪。
如果您被迫使用数组的手动内存管理(例如用于学习),则可以使用new[]
和delete[]
,或者您可以使用vector
或{ {1}}更严格的代码类。
答案 3 :(得分:-2)
使用std::vector
,它会自动为您处理所有内存管理。事实上,你几乎不需要面对std::stack
的Stack类,但这是另一回事。
此外,对于测试,不要以超级无意义的方式动态分配堆栈,只需创建一个本地堆栈。