在并集中的指针上删除



我尝试了一些有趣的代码(至少对我来说!)。给你。

#include <iostream>
struct myStruct{
int one;
/*Destructor: Program crashes if the below code uncommented*/
/*
~myStruct(){
std::cout<<"desn";
} 
*/
};
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;
}

我已将内存分配给charPtr,并使用structPtr删除。当我向myStruct添加析构函数时,它会崩溃,否则没有问题。

这里到底发生了什么。正如我所知,delete[]将调用析构函数的次数与new[]中给定的次数一样多。当myStruct中没有析构函数时,为什么它不崩溃?

首先,存储一个联合的一个成员,然后以您的方式读取另一个成员是Undefined Behavior,简单明了。这是错误的,任何事情都有可能发生。

除此之外,你尝试的联合双关语很可能真的有效(但请记住,这不是保证的)。如果是这种情况,则会发生以下情况:

您可以分配一个类型为charbytesToAllocate对象数组,并将地址存储在联合指针中。

然后,在类型为myStruct*的联合指针上调用delete[]。这意味着它假设它是一个myStruct对象的数组,并且它将在每个对象上调用析构函数。但是,该数组不包含任何myStruct对象,而是包含char对象。事实上,数组的字节大小甚至不是myStruct大小的倍数!必须彻底混淆delete的实现。它可能将第一个sizeof(myStruct)字节解释为一个myStruct对象,并调用这些字节中的析构函数。然后,只剩下不到sizeof(myStruct)个字节,但还有一些字节,所以在这些不完整的字节上调用析构函数,到达数组之外,然后就热闹起来了。

当然,由于这只是UB,我猜上面的行为可能有点离谱。简单明了,你混淆了它,所以它表现得很困惑。

delete做了两件事,调用析构函数和释放内存。

您为一种类型分配数据,但如果伪造另一种类型,则将其删除。你不应该这么做。在C/C++中有很多事情可以做,看看IOCCC可以获得更多灵感:-)

C++中没有任何函数并且只有普通旧数据的结构本身就是POD。在创建/删除时,它从不调用构造函数/析构函数。甚至不是标准的c-tors/d-tors。只是出于性能原因。

具有(EDIT)用户定义的副本分配运算符、虚拟函数或d-tor的结构在内部会稍微复杂一些。它有一个成员函数指针表。

如果用字符分配内存块,则该表不会初始化。当您尝试使用非POD类型删除此内存块时,它首先调用析构函数。由于析构函数指针没有初始化,它会调用内存空间中的任何内存块,以为它就是函数。这就是它崩溃的原因。

它之所以有效,是因为myStruct没有析构函数。[编辑:我现在看到你试过了,它确实崩溃了。我会发现这个问题很有趣,为什么它会和那个dtor一起崩溃,因为dtor不访问对象的任何内存。]

正如其他人所说,free[]的第二个功能除了可能调用元素的dtor(如前所述,这在这里不会发生)之外,就是释放内存。

这在您的实现中非常有效,因为通常免费存储实现只为此目的分配一块内存,其大小保存在该内存中的记账位置。大小(一旦分配)与类型无关,即不是从空闲时的指针类型派生的。参见如何删除[]";知道";操作数数组的大小?。类似malloc的、与类型无关的分配器返回内存块,并且很高兴。

当然,请注意,你所做的是令人难以置信的,不要在家里这样做,不要发布它,让ppl签署不承担责任的分歧,不要在核设施中使用它,并且总是从main()返回int。

问题是obj.U.structPtr指向一个结构,该结构可以有构造函数和析构函数。

delete还需要正确的类型,否则它无法调用析构函数。

因此,使用new创建char数组并将其作为struct指针删除是非法的。

如果你使用mallocfree就可以了。这不会调用构造函数和析构函数。

最新更新