解构函数中的堆损坏
Heap corruption in deconstructor
我正在创建一个程序来反编译一些游戏脚本文件。我添加的最新部分是在处理动态数组时给我一些错误。这是有问题的代码:
typedef struct _COD9_ANIMREF_1
{
DWORD name;
DWORD reference;
};
typedef struct _COD9_USEANIM_1
{
WORD name; // offset of name
WORD numOfReferences; // reference count
WORD numOfAnimReferences; // reference count
WORD null1; // always null
DWORD* references = NULL; // dynamic array of references, amount = numOfReferences
_COD9_ANIMREF_1* animReferences = NULL; // dynamic array of references, amount = numOfAnimReferences
~_COD9_USEANIM_1()
{
if (references)
delete[] references;
if (animReferences) // program officially breaks here, if continued causes heap corruption
delete[] animReferences;
}
};
typedef struct _COD9_WORK_1
{
_COD9_GSC_1 Hdr;
char* data = NULL;
int* includes = NULL; //done
_COD9_USEANIM_1* usingAnim = NULL; //not done, heap corruption
_COD9_STRING_1* strings = NULL; //done
_COD9_FUNC_1* functions = NULL; //done
_COD9_EXTFUNC_1* extFunctions = NULL; //done
_COD9_RELOC_1* relocations = NULL; //done
~_COD9_WORK_1()
{
if (data)
delete[] data;
if (includes)
delete[] includes;
if (usingAnim)
delete[] usingAnim;
if (strings)
delete[] strings;
if (functions)
delete[] functions;
if (extFunctions)
delete[] extFunctions;
if (relocations)
delete[] relocations;
}
};
if (tstg.Hdr.numOfUsinganimtree)
{
tstg.usingAnim = new _COD9_USEANIM_1[tstg.Hdr.numOfUsinganimtree];
igsc.seekg(tstg.Hdr.usinganimtreeStructs);
for (int i = 0; i < tstg.Hdr.numOfUsinganimtree; i++)
{
_COD9_USEANIM_1 anim;
igsc.read(reinterpret_cast<char*>(&anim.name), sizeof(anim.name));
igsc.read(reinterpret_cast<char*>(&anim.numOfReferences), sizeof(anim.numOfReferences)); // this is 0 in this instance
igsc.read(reinterpret_cast<char*>(&anim.numOfAnimReferences), sizeof(anim.numOfAnimReferences));
igsc.read(reinterpret_cast<char*>(&anim.null1), sizeof(anim.null1));
anim.references = new DWORD[anim.numOfReferences]; // allocate 0 size array so theres something to delete
if(anim.numOfReferences) // should not be entered
{
igsc.read(reinterpret_cast<char*>(&anim.references), (anim.numOfReferences*sizeof(DWORD))); // if numOfReference = 0, function should return
}
anim.animReferences = new _COD9_ANIMREF_1[anim.numOfAnimReferences];
for (int ii = 0; ii < anim.numOfAnimReferences; ii++)
{
_COD9_ANIMREF_1 animref;
igsc.read(reinterpret_cast<char*>(&animref.name), sizeof(animref.name));
igsc.read(reinterpret_cast<char*>(&animref.reference), sizeof(animref.reference));
anim.animReferences[i] = animref;
}
tstg.usingAnim[i] = anim;
printf("anim: %dn", i); // program reaches this
}
printf("Anims Donen"); // program doesn't reach this
ReorderUsingAnim(&tstg);
}
以下是正在读取的字段:
anim.name = 0x06BB
anim.numOfReferences = 0x0000
anim.numOfAnimReferences = 0x0001
anim.null1 = 0x0000
我认为错误发生的地方是引用数组,因为从技术上讲,在这种情况下大小为 0。但是我不确定该怎么做,而且总的来说,我对堆损坏也很迷茫。
_COD9_USEANIM_1
(为什么哦,为什么新手使用如此可怕的名字? 他们调用类似_Z_ASHD532___8AHQ_变量是否令人愉快??有两个数组(为什么不是向量??),references
和anim_references
. 它有一个析构函数,如果指针不为零,则释放数组。 但没有构造函数。 这是危险的。 您至少应该提供一个构造函数,该构造函数将它们初始化references
并anim_references
为零。 您还需要复制构造函数。 请记住规则:如果您提供三个(默认构造函数、析构函数、复制构造函数)之一,则几乎肯定需要所有三个。
好的,现在你开始循环
for (int i = 0; i < tstg.Hdr.numOfUsinganimtree; i++)
在循环中,您声明变量anim
_COD9_USEANIM_1 anim;
您可以分配其references
和animReferences
anim.references = new DWORD[anim.numOfReferences];
...
anim.animReferences = new _COD9_ANIMREF_1[anim.numOfAnimReferences];
最后,将其复制到tstg.usingAnim
tstg.usingAnim[i] = anim;
你知道复制它时会发生什么吗? 所有字段都只是复制。 所以现在references
和animReferences
tstg.usingAnim[i]
指向与动画references
和animReferences
相同的地址。
然后,块结束。 邪恶的计算机调用析构函数进行anim
。 析构函数调用 delete[] 用于 anim.references
和 anim.animReferences
。 但是,references
和animReferences
tstg.usingAnim[i]
都指向相同的地址。 换句话说,它们现在指向已删除的数组。
现在,堆的行为是不可预测的。
最好的建议:忘记数组,使用向量。你知道,std::vector
来自标准库。
第二好建议:提供默认构造函数和复制构造函数。(PS:和赋值运算符!
(请注意,您的程序也可能有其他错误。
- 动态构造函数中的新字符 [] 抛出"损坏的顶部大小";
- 调用std::函数成员时内存损坏
- 我的 c 字符串复制函数正在损坏其他变量的堆栈
- 构造函数初始化和对象损坏
- 动态分配时类构造函数中的堆损坏
- 从第三方库导出 cpp 损坏的函数
- 在使用新操作员和C 中的结构的调用构造函数时,获得内存损坏(Malloc)
- Win32 C API:替代损坏的execl*()系列函数?
- 对于我的类函数,我得到双重释放或损坏错误
- 堆损坏 c++ 返回表指针的函数
- 析构函数会导致堆损坏
- 为什么链表中的数据在嵌套函数中会更改/损坏?
- 有没有一种方法可以使用RTTI获得基于签名的typeinfo损坏的函数名
- 在向量中使用不带复制且没有 noexcept 移动构造函数的对象.实际损坏的内容以及我如何确认它
- 函数的返回类型是损坏名称的一部分吗?
- 当使用实例会员方法作为函数指针时,堆积损坏
- 从 dll 中的函数返回时堆损坏
- 在递归函数中释放内存时堆损坏
- 更新函数在 Azure 移动库中C++损坏
- eclipse g++没有损坏函数名