数组包装器损坏堆栈 [英] array wrapper corrupts stack

查看:63
本文介绍了数组包装器损坏堆栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目是像std :: vector这样的动态数组包装器.这是这样的:

my project is a dynamic array wrapper like std::vector. this is how it works:

  • 添加新元素时,如果内存为0,则分配内存(malloc),如果不为0,则以新大小重新分配内存(realloc).大小为元素数*类型的大小

  • when adding a new element, the memory is either allocated (malloc), if it is 0, or reallocated with a new size (realloc), if it is not 0. the size is the number of elements * size of type

当获得已经添加的元素时,我通过将其索引乘以类型的大小并将其添加到分配内存的地址来计算地址

when getting an already added element, i calculate the address by multiplying its index by the size of the type and adding it to the address at which the memory is allocated

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

NOTE: i write and read the memory myself with no function like memcpy or memset. this is required for my project. it should be possible for me to do this so if you could, do not mention it (unless i implemented it wrong, in which case, please do mention it)

当我尝试使用 get(int index)函数读取添加的元素时,我将收到变量周围的堆栈已损坏"或读取访问冲突"错误,具体取决于如何我尝试这样做.

when i try to read in an added element with the get(int index) function, i either get a "stack around variable was corrupted" or "read access violation" error, depending on how I try to do it.

我在网上阅读了一下,发现我可能已经用malloc破坏了堆.还阅读了我可以找出错误所在"valgrind"的地方,但是它似乎仅适用于linux,并且我使用的是Windows.

i read a bit online and found i may have corrupted the heap somehow with malloc. also read i could find out where the error is with something called "valgrind", but it seems to only be available for linux, and i use windows.

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

here is my code (its rewritten, all error checks were removed to make it smaller). the place where i get the error is commented:

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;
};

推荐答案

让我们拆开代码并慢慢修复它.从构造函数开始,应初始化所有内容.尽快初始化变量非常重要:

Lets take the code apart and fix it slowly. Starting with the constructor, everything should be initialized. It is very important that you initialize your variables as soon as possible:

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

现在让我们来看一下 add 方法.应该怎么办?在容器中添加一个元素,并保留已经存在的元素.现在正在做什么?让我们看看:

Now lets look at the method add. What should it do? Add an element to the container and retain the ones already existing. What is it doing right now? Lets see:

  1. 创建一个临时的 void * 指针.

void* end_temp = 0;

  1. 检查是否 end!= nullptr ,我们将 end 分配给 end_temp .
  1. Checking if end != nullptr, we assign end to end_temp.

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

  1. 分配内存并增加 elemc (我认为这是元素计数)
  1. Allocate memory and increasing the elemc (which I assume is element count)

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;
    }

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

Let's simplify and do just what we want, that is, add the element:

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

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

alloc() doesn't take an argument anymore because it is always increasing by 1. size is the number of elements in the container. We just assign the element to the last index, and increment the size by 1.

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

Let's see get() now. What does it need to do? Get the element at an index. Let's write it simply:

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

这篇关于数组包装器损坏堆栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆