C++ &引用;“双重自由或腐败”;实现动态数组数据结构时出错

C++ &引用;“双重自由或腐败”;实现动态数组数据结构时出错,c++,memory-management,destructor,dynamic-arrays,C++,Memory Management,Destructor,Dynamic Arrays,我试图为我的数据结构和算法课程实现一个动态数组数据结构,但我认为我在内存管理方面遇到了一些问题。我的模板类如下所示 ArrayList.h #include <iostream> #include <cstring> using namespace std; #define Length(array) (sizeof((array))/sizeof((array[0]))) template <class T> class ArrayList { p

我试图为我的数据结构和算法课程实现一个动态数组数据结构,但我认为我在内存管理方面遇到了一些问题。我的模板类如下所示

ArrayList.h

#include <iostream>
#include <cstring>
using namespace std;
#define Length(array) (sizeof((array))/sizeof((array[0])))

template <class T>
class ArrayList
{
    public:

    ArrayList() {a = new T[1]; n = 0;}
    ~ArrayList() {delete [] a;}

    int size();
    int backingSize();
    T get(int i);
    T set(int i, T x);
    void add(int i, T x);
    T remove (int i);

    private:

    void resize();

    T *a;
    int n;
};

template <class T>
int ArrayList<T>::size() { return n; }

template <class T>
int ArrayList<T>::backingSize() { return Length(a); }

template <class T>
T ArrayList<T>::get(int i) { return a[i]; }

template <class T>
T ArrayList<T>::set(int i, T x) 
{ 
    T temp = a[i];
    a[i] = x;
    return temp;
}

template <class T>
void ArrayList<T>::add(int i, T x) 
{
    if (n+1 > Length(a)) resize();
    for (int j = n; j > i; j--) a[j] = a[j-1];
    a[i] = x;
    n++;
}

template <class T>
T ArrayList<T>::remove(int i) 
{
    T temp = a[i];
    for (int j = i; j < n-1; j++) a[j] = a[j+1];
    n--; 
    if (Length(a) > 3*n) resize();
    return temp; 
}

template <class T>
void ArrayList<T>::resize() 
{
    if ( n+1 > Length(a))
    {
        cout << "Making Bigger\n"; 
        T* tempArr = new T[2*n];
        memcpy(tempArr, a, n * sizeof(T));
        delete [] a;
        a = tempArr;
    }

    else   //  (Length(a) > 3*n)
    {
        cout << "Making Smaller\n";
        T* tempArr = new T[n/2];
        memcpy(tempArr, a, n * sizeof(T));
        delete [] a;
        a = tempArr;
    }
}

它似乎按照预期工作,get函数在其索引处返回正确的值,size函数返回正确的数组长度,并且它们没有seg错误。但是,
backingSize()
函数总是返回2,并且我认为最后抛出的错误与糟糕的内存管理有关。我已经被难住了很长一段时间,所以如果有任何帮助,我将不胜感激。

您永远不应该在指针上使用
#定义长度(数组)(sizeof((数组))/sizeof((数组[0]))
。无法从指针知道数组的大小。这可能会导致你的问题。既然您有一个类,为什么不将大小和容量存储为变量呢?在处理数组类型的对象时,内存中占用的8个字节的大小和容量实际上什么都不是。

您显式地调用对象的析构函数。析构函数是自动调用的,因此由于您已经调用了析构函数,因此会发生双重自由错误

要了解何时调用析构函数,请查看此

这里有一个bug(不确定是否没有其他bug):


tempArr
只能保存
n/2
元素,但您尝试将
n
元素复制到其中。这是未定义的行为。此外,不可能为所有可能的类型逐字节复制元素
T

您还应该为您的类型定义一个复制构造函数、赋值运算符和移动赋值运算符(或删除它们)。首先使用调试器来确定您可能在何处点击
delete[]
两次?不要显式调用析构函数-当变量离开作用域时会自动调用它。
memcpy(tempArr,a,n*sizeof(t))如果
T
为非POD类型,则此功能将无法正常工作。例如,如果
T
std::string
,则此代码会导致未定义的行为。你的代码有很多错误,它超出了学习“数据结构和算法”的范围。C++不适合学习普通的“数据结构和算法”,除非你知道语言的所有细微差别。对于第一个,我的意思是它是两个以上的支持数组的长度。谢谢我不确定我是否完全理解你的第二部分。你是说memcpy()不能用于所有类型,但它在我的情况下可以工作,因为我正在使用int进行测试?@jasper它适用于
int
,因为
int
是可复制的。
#include "ArrayList.h"
#include <iostream>

using namespace std;

int main()
{
    ArrayList <int> myList;

    cout << myList.size() << "\n\n";

    myList.add(0,15);
    cout << myList.get(0) << ", " << myList.size() << ", " << myList.backingSize() << "\n";
    myList.add(1,34);
    cout << myList.get(1) << ", " << myList.size() << ", " << myList.backingSize() << "\n";
    myList.add(2,23);
    cout << myList.get(2) << ", " << myList.size() << ", " << myList.backingSize() << "\n";
    myList.add(3,1);
    cout << myList.get(3) << ", " << myList.size() << ", " << myList.backingSize() << "\n\n";

    myList.~ArrayList();
}
15, 1, 2
34, 2, 2
Making Bigger
23, 3, 2
Making Bigger
1, 4, 2

*** Error in `./TestArrayList': double free or corruption (fasttop): 0x000000000090c010 ***
Aborted
T* tempArr = new T[n / 2]; // the size is n / 2
memcpy(tempArr, a, n * sizeof(T)); // but here you try to copy n elements