Rei*_*ica 5 c++ gcc clang undefined-behavior pointer-conversion
我有以下功能模板:
template <class MostDerived, class HeldAs>
HeldAs* duplicate(MostDerived *original, HeldAs *held)
{
// error checking omitted for brevity
MostDerived *copy = new MostDerived(*original);
std::uintptr_t distance = reinterpret_cast<std::uintptr_t>(held) - reinterpret_cast<std::uintptr_t>(original);
HeldAs *copyHeld = reinterpret_cast<HeldAs*>(reinterpret_cast<std::uintptr_t>(copy) + distance);
return copyHeld;
}
Run Code Online (Sandbox Code Playgroud)
目的是复制特定类型的对象,并将其与由输入相同的子对象"保持".请注意,原则上,HeldAs可能是一个模糊或不可访问的基类MostDerived,因此没有演员可以在这里提供帮助.
这是我的代码,但它可以用于我控制之外的类型(即我无法修改MostDerived或HeldAs).该函数具有以下前提条件:
*original 属于动态类型 MostDerivedHeldAs是(MostDerived或MostDerived忽略cv-qualifiation)的直接或间接基类*held指的是*original其基类子对象或其中一个.让我们假设前提条件令人满意.duplicate在这种情况下是否定义了行为?
C++ 11 [expr.reinterpret.cast]说(大胆强调我的):
4指针可以显式转换为足以容纳它的任何整数类型.映射函数是实现定义的.[ 注意:对于那些了解底层机器的寻址结构的人来说,这并不奇怪.- 注意 ] ......
5可以将整数类型或枚举类型的值显式转换为指针.转换为足够大小的整数(如果实现上存在任何此类)并返回相同指针类型的指针将具有其原始值; 指针和整数之间的映射在其他方面是实现定义的.[ 注意:除3.7.4.3中描述的情况外,这种转换的结果不是安全派生的指针值.- 尾注 ]
好吧,假设我的编译器是GCC(或Clang,因为它使用GCC的实现定义行为的定义).引用GCC文档第5章关于C++实现定义的行为:
...有些选择记录在C语言的相应文档中.参见C实现....
到4.7章(C实现,数组和指针):
将指针转换为整数的结果,反之亦然(C90 6.3.4,C99和C11 6.3.2.3).
如果指针表示大于整数类型,则从指针到整数的转换丢弃最高有效位,如果指针表示小于整数类型则进行符号扩展,否则位不变.
如果指针表示小于整数类型,则从整数到指针的强制转换丢弃最高有效位,如果指针表示大于整数类型,则根据整数类型的符号扩展,否则位不变.
到现在为止还挺好.这似乎是因为我使用std::uintptr_t这是保证足够大的任何指针,因为我处理同一类型,copyHeld应指向相同HeldAs的子对象*copy的held指着内*original.
不幸的是,GCC文档中还有一个段落:
当从指针转换为整数并再次返回时,结果指针必须引用与原始指针相同的对象,否则行为是未定义的.也就是说,可能不会使用整数运算来避免指针运算的未定义行为,如C99和C11 6.5.6/8中所禁止的那样.
威猛.所以现在似乎即使copyHeld根据前两段的规则计算值,第三个仍然将其发送到Undefined-Behavior域.
我基本上有三个问题:
我的阅读是否正确duplicate且未定义的行为?
这是什么样的未定义行为?"正式未定义,但无论如何都会做你想要的",或"期望随机崩溃和/或自发的自焚"之一?
如果它确实是未定义的,有没有办法以明确定义的(可能依赖于编译器的)方式做这样的事情?
虽然就编译器而言,我的问题仅限于GCC(和Clang)行为,但我欢迎一个考虑各种硬件平台的答案,从普通桌面到异国情调.
通常的模式是将 a 放入clone()基类中。
然后每个派生类都可以实现自己的克隆版本。
class Base
{
public:
virtual Base* clone() = 0;
};
class D: public Base
{
virtual Base* clone(){ return new D(*this);}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
318 次 |
| 最近记录: |