数组包装器破坏堆

Array Wrapper Corrupts Heap

Sequel 至:

项目:

我正在研究 std::vector 替代品。

错误:

每当我尝试删除正在创建的临时数组以存储我删除的另一个数组的复制元素时,我都会收到堆损坏错误,以便在调整数组大小时重新分配它。 (似乎如果我尝试将一个数组分配给另一个数组,我实际上最终会将指向数组的指针分配给另一个数组而不是复制元素。真正疯狂的东西)。

我在网上看到这个错误实际上可能来自我实际与数组交互的部分,但只有在我尝试删除它时才会弹出这个错误。

我与数组交互的地方是函数 _tempcpy。我传递一个指向源和目标数组的指针,并将每个元素从源复制到目标。我努力确保数组从 0 而不是 1 开始,并且在这个过程中我对 element_count 成员搞得太多了,所以可能是我在某种程度上写在边界之外,我盯着代码看了这么多,我看不出问题所在。

代码:

template<class T> class dyn_arr
{
public:

    dyn_arr(void)
    {
        this->array         = {};
        this->element_count = {};
    }

    ~dyn_arr(void)
    {
        this->dealloc();
    }

    bool alloc(unsigned int element_count)
    {
        if (0 == element_count)
        {
            element_count = 1;
        }

        if (this->array != nullptr)
        {
            T* temp = new T[this->element_count];

            if (false == this->_tempcpy(&this->array, &temp, this->element_count))
            {
                return false;
            }

            delete[] this->array;
            this->array = new T[this->element_count];

            if (false == this->_tempcpy(&temp, &this->array, this->element_count))
            {
                return false;
            }

            delete[] temp;

            if (nullptr != this->array)
            {
                return true;
            }
        }
        else
        {
            this->array = new T[this->element_count];

            if (nullptr != this->array)
            {
                return true;
            }
        }

        return false;
    }

    bool dealloc(void)
    {
        if (nullptr == this->array)
        {
            return false;
        }

        delete[] this->array;

        return true;
    }

    bool add(T Object)
    {
        if (0 == Object)
        {
            return false;
        }

        if (true == this->alloc(this->element_count))
        {
            this->array[this->element_count] = Object;

            ++this->element_count;

            return true;
        }

        return false;
    }

    T get(unsigned int index)
    {
        if (index > this->element_count)
        {
            return T{};
        }

        return this->array[index];
    }

    unsigned int get_count(void)
    {
        return this->element_count;
    }

private:

    bool _tempcpy(T** src, T** dest, unsigned int count)
    {
        if ((nullptr == src) || (nullptr == dest) || (0 == count))
        {
            return false;
        }

        for (unsigned int i = 0; i < count; ++i)
        {
            *dest[i] = *src[i];
        }

        return true;
    }

    T* array;
    unsigned int element_count;
};

int main()
{
    dyn_arr<int> pNr = {};
    pNr.add(1);
    pNr.add(2);
    pNr.add(3);

    for (int i = 0; i < pNr.get_count(); ++i)
    {
        printf("%d\n", pNr.get(i));
    }

    getchar();
    return 0;
}

在你的alloc函数中存在一些问题,例如:

if (0 == element_count)
{
        element_count = 1;
}

不需要。相反,您可以只在必要时执行 +1 ,除了 temp 动态数组之外几乎无处不在。

bool alloc(...)
{
    this->array = new T[this->element_count];
    //...
    else
    {
       this->array = new T[this->element_count];  
    }
}

应该是

    this->array = new T[this->element_count + 1];
    //...
    else
    {
       this->array = new T[this->element_count + 1];  
    }

这将解决分配问题。这给我们留下了 _tempcpy() ,它失败了,因为它没有尝试获取底层数组的下一个元素,而是尝试使用双指针本身来做到这一点。阅读有关运算符优先级规则的信息。固定版本:

    bool _tempcpy(T** src, T** dest, unsigned int count)
    {
       //....
        for (unsigned int i = 0; i < count; ++i)
        {
            (*dest)[i] = (*src)[i];
        }
        //....
    }

但是,我不确定为什么这个函数首先需要 double ptr。只需使用单指针。另外 dest 应该是 const 因为它在这个函数中没有改变。它让函数的 reader 清楚地知道哪些参数会在函数内部改变,哪些不会:

bool _tempcpy(T* src, const T* dest, unsigned int count) {...}

同样适用于class的其他部分。

此外,在 C++ 中

dyn_arr(void)

我们不这样做。没有必要显式写 void。根据 C++ 标准:

8.3.5 Functions [dcl.fct] ... A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.