c++ - 使用一个类的两个单独实例时出现 Malloc 错误 2372

标签 c++ class malloc

为了清楚起见,这个错误来自学校作业的程序,但错误本身与 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++ 经验。

*编辑:将析构函数更改为不删除大小和容量,并在重新调整数组大小之前向插入函数添加删除 A 行。

最佳答案

遗憾的是我之前没有发现这个。回答完我就跳上我的剑。

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 h1h2,一些目前尚未完成。

现在如果你不介意的话,我必须找到我放剑的地方。

关于c++ - 使用一个类的两个单独实例时出现 Malloc 错误 2372,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34167961/

相关文章:

编译自定义 malloc

c++ - 需要从 C++ 中的派生类调用基本析构函数方法?

c++ - 通过Visual C++访问串口

c - 错误: Conflicting types in structs pointers

optimization - 内存分配的时间复杂度

Java 类未找到异常,但位于同一个 src 文件夹中

c++ - Qt 使用 singleShot Timer 从 QGraphicsScene 中删除 QGraphicsItem?

c++ - 在什么时候取消引用空指针会变成未定义的行为?

class - 使用类模块将可编辑的ADO记录集返回到MS Access Form

c++ - 调用虚函数的逻辑不清晰(或者是方法隐藏?)