由于realloc,程序崩溃

时间:2015-10-08 17:20:34

标签: c++ stack dynamic-memory-allocation realloc

我正在尝试构建一个自我调整大小的堆栈,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

的末尾崩溃了

如果有人解释我做错了什么,我将不胜感激。

4 个答案:

答案 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%正确的。首选newdelete优先于malloc()free(),而不是您自己的自制堆栈实现上的标准库容器。

无论如何,这里的真正问题是,realloc()可能会分配一个新的内存块并释放旧的内存块。它返回一个指向新指针的指针。

正确的电话是:

*st = realloc(*st, sizeof(int) * (*length));

现在*st将存储新指针,一切都很好。

考虑使用标准库,而不是实现自己的基础数据结构。它有一个设计良好的界面,并经过了彻底的测试。

答案 2 :(得分:2)

最终崩溃很可能是因为您将newfree混合在一起。这是未定义的行为。它可能适用于某些系统,但绝不是一个好主意。您应该将newdelete配对。对malloc的呼叫与free配对,但这些更多用于C代码。 C ++代码通常使用newdelete

当然,您可以通过将new设为局部变量来消除myStack

Stack myStack;

您还需要调整成员访问权限才能使用.而不是->。没有必要删除myStack,因为一旦函数退出,局部变量将自动清除,包括异常情况。

还注意到realloc的返回值被忽略。如果当前内存块不能被realloc扩展,它必须分配一个新的内存块并将旧数据复制到它。在这种情况下会返回一个新指针,因此必须更新st

*st = realloc(*st, sizeof(int) * (*length));

但是,再次使用mallocreallocfree在C ++代码中有点奇怪。

如果您被迫使用数组的手动内存管理(例如用于学习),则可以使用new[]delete[],或者您可以使用vector或{ {1}}更严格的代码类。

答案 3 :(得分:-2)

使用std::vector,它会自动为您处理所有内存管理。事实上,你几乎不需要面对std::stack的Stack类,但这是另一回事。

此外,对于测试,不要以超级无意义的方式动态分配堆栈,只需创建一个本地堆栈。