数组包装器损坏堆栈

array wrapper corrupts stack

我的项目是一个类似于 std::vector 的动态数组包装器。它是这样工作的:

注意:我自己写入和读取内存,没有像 memcpy 或 memset 这样的功能。这是我的项目所必需的。我应该可以做到这一点,所以如果可以,请不要提及(除非我实施错误,在这种情况下,请提及)

当我尝试使用 get(int index) 函数读取添加的元素时,我会收到 "stack around variable was corrupted" 或 "read access violation" 错误,具体取决于我尝试的方式。

我在网上看了一点,发现我可能已经用 malloc 以某种方式破坏了堆。还读了我可以找出错误的地方是 "valgrind",但它似乎只适用于 linux,我使用 windows.

这是我的代码(重写,删除了所有错误检查以使其更小)。我得到错误的地方评论:

template<class T>
class darr
{
public:
    darr(void) {}
    ~darr(void) {
        erase(); dealloc();
    }

    bool alloc(int elemc) {
        this->elemc = elemc;
        this->size = (elemc * sizeof(T));
        this->end = (this->start + this->size);

        if (this->start)
        {
            this->start = (T*)(realloc(this->start, this->size));

            if (this->start)
            {
                this->end = (this->start + this->size);
                return true;
            }
        }
        else
        {
            this->start = (T*)(malloc(this->size));

            if (this->start)
            {
                this->end = (this->start + this->size);
                return true;
            }
        }

        return false;
    }

    bool erase(void)
    {
        for (int i = 0; i <= this->size; ++i)
        {
            *(unsigned long*)(this->start + i) = 0;
        }

        return true;
    }

    bool dealloc(void)
    {
        free(this->start);

        return true;
    }

    bool add(T obj)
    {
        void* end_temp = 0;

        if (this->end) { end_temp = this->end; }

        if (true == this->alloc(++this->elemc))
        {
            end_temp = this->end;

            for (int i = 0; i <= sizeof(obj); ++i)
            {
                *(unsigned long*)((unsigned long)(end_temp)+i) = *(unsigned long*)((unsigned long)(&obj) + i);
            }
        }

        return true;
    }

    T get(int i)
    {
        unsigned long siz = sizeof(T);
        void* i_addr = this->start + (i * siz);

        //T tempobj = 0;
        T* tempobj = (T*)(malloc(sizeof(T)));
        // without malloc - stack around var corrupted (happnens at last index in for loop, no matter what index it is)
        // with malloc - read access violation
        for (int i = 0; i <= siz; ++i)
        {
            *(unsigned long*)((unsigned long)(&tempobj)+i) = *(unsigned long*)((unsigned long)(i_addr)+i);
        }

        return *tempobj;
    }
private:
    T * start;
    void* end;
    int elemc, size;
};

让我们把代码拆开慢慢修复。从构造函数开始,一切都应该被初始化。尽快初始化变量非常重要:

    darr() {
        start = nullptr;
        end = nullptr;
        elemc = 0;
        size = 0;
    }

现在让我们看一下方法add。它应该做什么?向容器中添加一个元素并保留已经存在的元素。它现在在做什么?让我们看看:

  1. 正在创建临时 void* 指针。
void* end_temp = 0;
  1. 检查是否 end != nullptr,我们将 end 分配给 end_temp
if (this->end) { end_temp = this->end; }
  1. 分配内存并增加 elemc(我假设是元素数)
if (true == this->alloc(++this->elemc))
  1. 下一个??我不知道。我也不确定这与将元素添加到容器的简单任务有什么关系:
{
     end_temp = this->end;

            for (int i = 0; i <= sizeof(obj); ++i)
            {
                *(unsigned long*)((unsigned long)(end_temp)+i) = *(unsigned long*)((unsigned long)(&obj) + i);
            }
        }

        return true;
    }

让我们简化并做我们想要的,即添加元素:

        if (true == this->alloc())
        {
            start[size] = obj;
            this->size++;
        }

alloc() 不再接受参数,因为它总是递增 1。size 是容器中元素的数量。我们只是将元素分配给最后一个索引,并将大小增加 1。

让我们现在 get() 看看。它需要做什么?获取索引处的元素。简单写一下:

T get(int i) const
{
    if (i < size)
        return start[i];
}