sha*_*oth 17 c++ memory-management undefined-behavior visual-c++
在我的代码中,我实际上有以下内容:
wchar_t* buffer = new wchar_t[size];
// bonus irrelevant code here
delete[] reinterpret_cast<char*>( buffer );
Run Code Online (Sandbox Code Playgroud)
有问题的类型都是内置的,因此它们具有琐碎的析构函数.在VC++中,上面的代码可以正常工作 - new[]只需分配内存,然后delete[]释放它.
在C++中可以接受吗?是不确定的行为?
Ste*_*sop 18
我最初的想法是它是未定义的行为.
5.3.5/3:"在第二种方法(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为是未定义的.73).
脚注73写道:"这意味着无法使用类型指针删除void*对象,因为没有类型的对象void".
可以说,在你的榜样的对象不具有动态类型,因为在1.3.3"动态型"的定义中提到了"最派生对象",并在1.8/4"最派生类对象"的定义是在谈论对象类类型.所以我一直在寻找:
5.2.10/3:"[reinterpret_cast]可能会或可能不会产生与原始值不同的表示"
5.3.5/2:"操作数的
delete值应该是由前一个数组new-expression产生的指针值 ".
我不确定reinterpret_cast是否会产生与输入相同的指针值.可能它已被我尚未找到的标准的其他一些部分清除.我不会在没有找到明确声明如果你重新解释一个指针的情况下调用这个代码"OK",结果是与之前相同的"指针值",所以通过传递给delete []你传递"指针值" "来自new [].
5.2.10/7:"除了某些指针类型之间的转换和返回其原始类型产生原始指针值之外,这种指针转换的结果是未指定的".
这看起来对我来说是个坏消息 - 它显然并没有说演员阵容产生相同的价值,只有那些演员阵容反过来,产生相同的价值.这告诉我,单一演员阵容可以产生不同的价值,但这只是暗示,而不是明确的.这是规则的常见问题,"如果标准没有说明行为,那么行为是未定义的".仅仅因为它没有在我使用索引找到的任何段落中说明它,并不意味着它没有在其他地方陈述它...
我们知道在实践中我们可以将事物转换为unsigned char*以检查它们的字节,或者使用memcpy来复制POD,因此必须有一些转换保证创建别名.您可能会认为如果您的实现确实创建了具有某些强制类型转换的别名,那么您传递的是从new []获得的"相同值".但我仍然不确定删除[]是否足够好.我想我错过了一些重要的事情.
它是未定义的行为,因为delete[]调用了错误的析构函数.但是,wchar_t并且char是POD,因此它们没有专用的析构函数,并且所有delete[]操作都是调用堆实现以释放指针.因此,它最有可能工作,没有字节丢失.但严格来说,它仍然是未定义的.
至少在我读它时,你有一个静态类型(指针的类型),它不同于动态类型(它所指向的对象的真实类型).既然如此,§5.3.5/ 3的第二句适用:
在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义.
编辑:因为你显然想要的是分配一个"原始"内存缓冲区而不是一个对象数组,我建议使用::operator new而不是new[].在这种情况下,您正在做的事情已经明确定义,并且还为读者提供了明确的意图指示.
iso14882 第 5.2.10.3 节:
The mapping performed by reinterpret_cast is is implementation defined
iso14882 第 5.3.5.2 节:
The value of the operand of delete[] shall be the pointer value which resulted from a previous array new-expression
换句话说,它的实现定义了 delete[] 是否调用未定义的行为。避开。
| 归档时间: |
|
| 查看次数: |
3519 次 |
| 最近记录: |