为了清楚起见,这个错误来自学校作业的程序,但错误本身与malloc的问题有关,而不是理解作业。在作业中我只使用了这个类的一个实例,所以这个问题主要是为了将来参考。当我使用在此声明的Heap类的2个不同实例时,我遇到的问题出现了:
a4.h
#include <iostream>
using namespace std;
/*
Class Declarations
********************************************************************
*/
// A Heap implemented with a growing array
class Heap{
public:
Heap();
~Heap();
void insert ( int item );
int remove();
void printheap();
private:
void trickleup ( int pos );
void trickledown ( int pos );
void swap ( int pos1 , int pos2 );
int* A;
int size;
int capacity;
};
/*
Class Methods
*********************************************************************
*/
// For Heap
Heap::Heap(){
A = NULL;
size = 0;
capacity = 0;
}
Heap::~Heap(){
delete A;
}
void Heap::insert ( int item ){
if ( size == capacity ){
int* newpointer = new int[(capacity*2)+1];
for (int i = 0; i < size; i++) newpointer[i] = A[i];
delete A;
A = newpointer;
}
A[size] = item;
size += 1;
trickleup (size-1);
return;
}
int Heap::remove(){
size -= 1;
int temp = A[0];
swap ( 0 , size );
trickledown (0);
return temp;
}
void Heap::printheap(){
cout << "Root -> [ ";
for (int i = 0; i < size; i++) cout << A[i] << " ";
cout << "]\n";
return;
}
void Heap::trickleup ( int pos ){
int p0 = pos;
int p1 = (pos-1)/2;
if ( p0 == 0 ){
trickledown (0);
return;
}
if ( A[p0] > A[p1] ){
swap ( p0 , p1 );
trickleup ( p1 );
}
else trickledown (p0);
return;
}
void Heap::trickledown ( int pos ){
int p0 = pos;
int p1 = (2*pos)+1;
int p2 = (2*pos)+2;
if ( p1 >= size ) return;
if ( p2 >= size ){
if ( A[p0] < A[p1] ) swap ( p0 , p1 );
return;
}
bool f1 = ( A[p0] < A[p1] );
bool f2 = ( A[p0] < A[p2] );
if ( (A[p1] >= A[p2]) && f1 ){
swap ( p0 , p1 );
trickledown ( p1 );
}
else if ( (A[p1] < A[p2]) && f2 ){
swap ( p0 , p2 );
trickledown ( p2 );
}
return;
}
void Heap::swap ( int pos1 , int pos2 ){
int temp = A[pos1];
A[pos1] = A[pos2];
A[pos2] = temp;
return;
}
我使用new
来请求内存的唯一时间是插入函数。
当我运行从 htest.cpp 编译的测试程序并运行h1测试和h2测试的两个部分时,会出现问题。如果我只运行两个测试中的一个,则问题不会发生。这是测试程序:
htest.cpp
#include <cstdlib>
#include <iostream>
#include "a4.h"
using namespace std;
int main(){
cout << "\nCreating h1 And h2\n\n";
Heap* h1 = new Heap();
Heap* h2 = new Heap();
cout << "\nAdding 0-6 To h1\n\n";
h1->insert ( 0 ); cout << "h1: "; h1->printheap();
h1->insert ( 1 ); cout << "h1: "; h1->printheap();
h1->insert ( 2 ); cout << "h1: "; h1->printheap();
h1->insert ( 3 ); cout << "h1: "; h1->printheap();
h1->insert ( 4 ); cout << "h1: "; h1->printheap();
h1->insert ( 5 ); cout << "h1: "; h1->printheap();
h1->insert ( 6 ); cout << "h1: "; h1->printheap();
cout << "\nRemoving All Elements From h1\n\n";
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "\nAdding 6-0 To h2\n\n";
h2->insert ( 6 ); cout << "h2: "; h2->printheap();
h2->insert ( 5 ); cout << "h2: "; h2->printheap();
h2->insert ( 4 ); cout << "h2: "; h2->printheap();
h2->insert ( 3 ); cout << "h2: "; h2->printheap();
h2->insert ( 2 ); cout << "h2: "; h2->printheap();
h2->insert ( 1 ); cout << "h2: "; h2->printheap();
h2->insert ( 0 ); cout << "h2: "; h2->printheap();
cout << "\nRemoving All Elements From h2\n\n";
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "\n";
return 0;
}
编译完程序并运行它(使用GNU C ++编译器)后,得到以下输出:
输出
Creating h1 And h2
Adding 0-6 To h1
h1: Root -> [ 0 ]
h1: Root -> [ 1 0 ]
h1: Root -> [ 2 0 1 ]
h1: Root -> [ 3 2 1 0 ]
h1: Root -> [ 4 3 1 0 2 ]
h1: Root -> [ 5 3 4 0 2 1 ]
h1: Root -> [ 6 3 5 0 2 1 4 ]
Removing All Elements From h1
Removed: 6 h1: Root -> [ 5 3 4 0 2 1 ]
Removed: 5 h1: Root -> [ 4 3 1 0 2 ]
Removed: 4 h1: Root -> [ 3 2 1 0 ]
Removed: 3 h1: Root -> [ 2 0 1 ]
Removed: 2 h1: Root -> [ 1 0 ]
Removed: 1 h1: Root -> [ 0 ]
Removed: 0 h1: Root -> [ ]
Adding 6-0 To h2
htest: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
Aborted (core dumped)
我想知道为什么会出现这个错误,因为它似乎没有做任何非法请求内存的事情。如果有人可以尝试清楚解释问题,我会非常感激,因为我只有大约一年的C ++经验。
*编辑:更改析构函数以不删除大小和容量,并在重新调整数组大小之前向insert函数添加了删除A行。
答案 0 :(得分:1)
很遗憾我之前没有发现过这个。回答之后,我会把自己扔到剑上。
Heap::insert
从未设置capacity
。它保持为0,因此在第一个之后插入不会触发if (size == capacity)
并且不会调整A
的大小。结果,A
超出了边界并破坏了堆(内存堆,而不是类Heap
)。
我推荐一个小编辑:
void Heap::insert(int item)
{
if (size == capacity)
{
capacity = (capacity * 2) + 1; // Note: many tests have shown that 1.5 is a
// better expansion factor than 2.
int* newpointer = new int[capacity];
for (int i = 0; i < size; i++)
newpointer[i] = A[i];
delete A;
A = newpointer;
}
A[size] = item;
size += 1;
trickleup(size - 1);
return;
}
另外
Heap* h1 = new Heap();
Heap* h2 = new Heap();
不需要动态分配,可以定义为
Heap h1;
Heap h2;
临时分配带来的其他优势,例如改进的空间局部性,这不需要程序员delete
h1
和h2
,这是目前尚未完成的事情。
现在,如果你能原谅我,我必须找到我离开剑的地方。