【发布时间】:2019-05-17 06:40:00
【问题描述】:
对于一个实验室任务,我正在研究堆的数组实现。我有一个PrintJob * 类型的数组。我面临的问题是我尝试使用delete 删除的第一个元素arr[0] 奇怪地修改了数组的第二个元素。最终,该元素到达堆的头部,删除它会导致 SIGABRT。
我原本想也许直接从数组中删除它,delete arr[0] 发出某种类型的错误,因为我会反复调用delete arr[0];尽管如此,我在删除arr[0] 后立即将其更新为下一个最大的孩子。所以,我尝试将它存储到一个临时变量中,然后将其删除:
void dequeue() {
PrintJob *temp = arr[0];
//// delete arr[0];
trickleUp(0);
delete temp;
}
但我很快意识到我的努力没有任何意义。我知道当程序尝试两次删除动态分配的实体时会发生 SIGABRT,但除了第一个元素之外,我从未触及任何其他元素。所以我很困惑为什么第二个元素被垃圾值填充,然后抛出 SIGABRT。
这是我使用的其他一些代码:
这个函数由上面的函数调用,控制将当前索引(n's)的最大子元素移动到它的位置的过程。它根据要求递归地执行此操作。
void trickleUp(int n) {
int c = getChild(n, true); // get the greater child
if (c >= MAX_HEAP_SIZE) { // if the
PrintJob *temp = arr[n];
//// delete arr[n];
arr[n] = nullptr;
delete temp;
return;
}
arr[n] = arr[c]; // update the old node
trickleUp(c); // move to the next element in the tree;
}
getChild() 是由前一个函数调用的函数,旨在返回当前索引n 的最大子索引(ln:左节点,rn:右节点)。
int getChild(int n, bool g) {
int ln = (2 * n) + 1, rn = (2 * n) + 2, lp = -1, rp = -1;
if (ln < MAX_HEAP_SIZE && arr[ln]) {
lp = arr[ln]->getPriority();
}
if (rn < MAX_HEAP_SIZE && arr[rn]) {
rp = arr[rn]->getPriority();
}
return ( !((lp > rp) ^ g) ? ln:rn );
}
我已经多次检查代码,也没有看到任何其他逻辑错误,当然,直到这个问题得到解决并且我能够用额外的样本进行测试,我才能真正说出.如果您想自己编译,这里是所有其余代码的链接。我也附上了一个makefile。 https://drive.google.com/drive/folders/18idHtRO0Kuh_AftJgWj3K-4OGhbw4H7T?usp=sharing
【问题讨论】:
-
请在没有外部链接的问题中提供minimal reproducible example。
-
arr[n] = arr[c];看起来有点可疑,你现在有相同的指针存储在两个不同的地方? -
直到我将 arr[c] 更新为下一行
trickleUp(c)中的下一个最大的孩子。你还建议我改吗? -
您需要调试您的代码,但由于您怀疑双重释放,那么您的代码中重复指针的部分可能是一个很好的起点
-
请发帖minimal reproducible example。如果做不到这一点,我可以提供毫无根据的猜测和挥手。
标签: c++ arrays heap delete-operator sigabrt