程序因 realloc 而崩溃

Program crashes because of 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 以便能够将其重新用于 pop):

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 结束时崩溃了。

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

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

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

Stack myStack;

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

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

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

但同样,在 C++ 代码中使用 mallocreallocfree 有点奇怪。

如果您被迫使用数组的手动内存管理(例如为了学习),您可以使用 new[]delete[],或者您可以使用 vectorstack 类 更严肃的代码。

撞车是你的幸运。这是未定义的行为。

让我们看看 Bjarne Stroustrup 在 here 中是怎么说的:

No, in the sense that you cannot allocate an object with malloc() and free it using delete. Nor can you allocate with new and delete with free() or use realloc() on an array allocated by new.

The C++ operators new and delete guarantee proper construction and destruction; where constructors or destructors need to be invoked, they are. The C-style functions malloc(), calloc(), free(), and realloc() doesn't ensure that. Furthermore, there is no guarantee that the mechanism used by new and delete to acquire and release raw memory is compatible with malloc() and free(). If mixing styles works on your system, you were simply "lucky" - for now.

C++ FAQ 对此也有专门的条目:

https://isocpp.org/wiki/faq/freestore-mgmt#realloc-and-renew

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

另外为了测试不要超级无意义的动态分配Stack,只做一个本地Stack。

所有那些说 malloc()free() 在 C++ 中是个坏主意的人都是 100% 正确的。比 malloc()free() 更喜欢 newdelete 并且比你自己的自制堆栈实现更喜欢标准库容器。

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

正确的叫法是:

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

现在*st将存储新指针,一切正常。

考虑使用标准库,而不是实现您自己的基本数据结构。它有一个精心设计的界面,并且经过了非常彻底的测试。