我尝试了一些有趣的代码(至少对我而言!).这里是.
#include <iostream>
struct myStruct{
int one;
/*Destructor: Program crashes if the below code uncommented*/
/*
~myStruct(){
std::cout<<"des\n";
}
*/
};
struct finalStruct {
int noOfChars;
int noOfStructs;
union {
myStruct *structPtr;
char *charPtr;
}U;
};
int main(){
finalStruct obj;
obj.noOfChars = 2;
obj.noOfStructs = 1;
int bytesToAllocate = sizeof(char)*obj.noOfChars
+ sizeof(myStruct)*obj.noOfStructs;
obj.U.charPtr = new char[bytesToAllocate];
/*Now both the pointers charPtr and structPtr points to same location*/
delete []obj.U.structPtr;
}
Run Code Online (Sandbox Code Playgroud)
我已将内存分配给charPtr并使用structPtr删除.当我向myStruct添加析构函数时崩溃,否则没有问题.
这到底发生了什么.据我所知,delete []将调用析构函数的次数与new []中给出的次数相同.为什么在myStruct中没有析构函数时它不会崩溃?
首先,存储一个union的一个成员,然后以你正在做的方式读取另一个成员是Undefined Behavior,简单明了.这是错的,任何事情都可能发生.
除此之外,你尝试使用联盟的类型双关语很可能实际上有效(但请记住它不能保证).如果是这种情况,会发生以下情况:
您分配bytesToAllocate类型的对象数组char并将地址存储在unionized指针中.
然后,调用类型为delete[]的联合指针.这意味着它假设它是一个对象数组,它将调用每个对象上的析构函数.但是,该数组不包含任何对象,它包含对象.实际上,数组的字节大小甚至不是大小的倍数!该实施必须彻底混淆.它可能将第一个字节解释为一个对象,并在这些字节中调用析构函数.然后,还剩下少于几个字节,但仍有一些剩余,所以析构函数在那些不完整的字节上被调用,超出数组,并且随之而来的是欢闹.myStruct*myStructmyStructcharmyStructdeletesizeof(myStruct)myStructsizeof(myStruct)
当然,由于这只是UB,我对上述行为的猜测可能会有所不同.平淡而简单,你已经把它搞糊涂了,所以它很混乱.