C++ 数组包装会损坏堆栈
我的项目是一个类似std::vector的动态数组包装器。这就是它的工作原理:C++ 数组包装会损坏堆栈,c++,memory-management,heap-memory,heap-corruption,C++,Memory Management,Heap Memory,Heap Corruption,我的项目是一个类似std::vector的动态数组包装器。这就是它的工作原理: 添加新元素时,如果内存为0,则分配内存(malloc),如果内存不是0,则使用新大小(realloc)重新分配内存。大小是元素数*类型大小 当获取一个已经添加的元素时,我通过将其索引乘以类型的大小并将其添加到分配内存的地址来计算地址 注意:我自己写和读内存,没有像memcpy或memset这样的函数。这是我的项目所必需的。我应该可以这样做,如果你可以的话,不要提它(除非我实施错误,在这种情况下,请提它) 当我尝试
- 添加新元素时,如果内存为0,则分配内存(malloc),如果内存不是0,则使用新大小(realloc)重新分配内存。大小是元素数*类型大小
- 当获取一个已经添加的元素时,我通过将其索引乘以类型的大小并将其添加到分配内存的地址来计算地址
get(int index)
函数读入一个添加的元素时,我会得到一个“stack around variable was corrupted”或“read access invalization”错误,具体取决于我的操作方式
我在网上读了一些文章,发现我可能用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(void){}
~darr(无效){
擦除();解除锁定();
}
布尔alloc(内部电气){
这->elemc=elemc;
这个->大小=(elemc*sizeof(T));
此->结束=(此->开始+此->大小);
如果(此->开始)
{
this->start=(T*)(realloc(this->start,this->size));
如果(此->开始)
{
此->结束=(此->开始+此->大小);
返回true;
}
}
其他的
{
这个->开始=(T*)(malloc(这个->大小));
如果(此->开始)
{
此->结束=(此->开始+此->大小);
返回true;
}
}
返回false;
}
布尔擦除(无效)
{
对于(int i=0;i size;++i)
{
*(无符号长*)(此->开始+i)=0;
}
返回true;
}
bool DEALOC(无效)
{
自由(此->开始);
返回true;
}
布尔加法(T obj)
{
void*end_temp=0;
如果(this->end){end\u temp=this->end;}
if(true==this->alloc(++this->elemc))
{
结束温度=此->结束;
对于(int i=0;i start+(i*siz);
//T-tempobj=0;
T*tempobj=(T*)(malloc(sizeof(T));
//在没有malloc的情况下,var周围的堆栈已损坏(在for循环中的最后一个索引处出现happnens,无论它是什么索引)
//使用malloc-读取访问冲突
对于(int i=0;i让我们将代码拆开并慢慢修复。从构造函数开始,所有内容都应该初始化。尽快初始化变量非常重要:
darr(){
开始=空PTR;
end=nullptr;
elemc=0;
尺寸=0;
}
现在让我们看一下方法add
。它应该做什么?向容器中添加一个元素并保留已经存在的元素。它现在正在做什么?让我们看看:
创建临时void*
指针
void*end_temp=0;
检查end!=nullptr
,我们将end
分配给end\u temp
if(this->end){end\u temp=this->end;}
分配内存并增加elemc
(我假设是元素计数)
if(true==this->alloc(++this->elemc))
接下来??我不确定。我也不确定这与将元素添加到容器的简单任务有什么关系:
{
结束温度=此->结束;
对于(int i=0;i让我们将代码拆开并慢慢修复。从构造函数开始,所有内容都应该初始化。尽快初始化变量非常重要:
darr(){
开始=空PTR;
end=nullptr;
elemc=0;
尺寸=0;
}
现在让我们看一下方法add
。它应该做什么?向容器中添加一个元素并保留已经存在的元素。它现在正在做什么?让我们看看:
创建临时void*
指针
void*end_temp=0;
检查end!=nullptr
,我们将end
分配给end\u temp
if(this->end){end\u temp=this->end;}
分配内存并增加elemc
(我假设是元素计数)
if(true==this->alloc(++this->elemc))
接下来??我不确定。我也不确定这与将元素添加到容器的简单任务有什么关系:
{
结束温度=此->结束;
对于(int i=0;i)来说,我确实把它复杂化得很糟糕。add
中的代码是在考虑“复制memcpy函数”的情况下编写的,因此我试图逐字节地将每个字节从源代码复制到目标代码,但我把“逐字节”的代码弄错了正如我后来了解到的。关于初始化,现在不是所有的东西都是由编译器自动初始化的吗?请记住,对于逐字节,您应该始终使用char*
reinterpret\u cast
只能与char*
一起使用,因为几乎所有其他东西都会破坏您的整个程序。请参阅以下内容:不,只有全局变量和静态变量被初始化为0,如果它们是本地类型,比如int
/long
。其他所有的东西都需要初始化,本地变量,类成员我现在看到了。我个人不太了解UB,你给我的链接更多地谈到了一行或多行代码可能是错误的由t解释