将reinterpret_cast输入重新解释为std :: unique_ptr是不是真的安全?

时间:2015-03-04 06:22:23

标签: c++ pointers c++11 unique-ptr reinterpret-cast

当使用具有可变大小结构的各种API(必须分配为byte []然后转换为结构的结构)时,如果unique_ptr持有者可以指向结构,那将是很好的,因为#39; s我们将要使用的东西。

示例:

std::unique_ptr<VARIABLE_SIZE_STRUCT[]> v; 
v.reset(reinterpret_cast<VARIABLE_SIZE_STRUCT*>(new BYTE[bytesRequired]));

这允许`v为结构本身提供视图,这是优选的,因为我们不需要第二个变量,除了删除之外我们不关心字节指针。

问题在于可能会在演员表上敲击指针(使其免于安全)。我认为没有合理的理由为什么编译器会改变转换时的指针值(因为没有继承),但是我听说标准保留了在任何转换中使用任何指针的权利,所以标准兼容编码去了,这种方法是窗外的吧?或者有什么理由它是安全的吗?有没有办法至少static_assert这个,或其他一些方法来使它安全或干净地处理这种类型的结构?

2 个答案:

答案 0 :(得分:5)

你是对的,这是不安全的。但是,它可以使它安全。

该标准保证如果您reinterpret_cast为其他类型,然后返回原始类型,则会返回原始值。

您可以将它与自定义删除器一起使用,以确保将内部指针强制转换为释放它之前分配的类型。

auto deleter = [](VARIABLE_SIZE_STRUCT* ptr) 
{ 
    delete[] reinterpret_cast<uint8_t*>(ptr); 
}; 

std::unique_ptr<VARIABLE_SIZE_STRUCT, decltype(deleter)> v
    (reinterpret_cast<VARIABLE_SIZE_STRUCT*>(new uint8_t[256]), deleter);

此时,您可能最好不要创建自己的包装而不使用unique_ptr

答案 1 :(得分:5)

  • 您的分配可能没有VARIABLE_SIZE_STRUCT

  • 所需的对齐方式
  • 分配的内存中没有VARIABLE_SIZE_STRUCT位置的对象 - new在其中 - 假设您处理它,unique_ptr的默认析构函数逻辑应该找到要销毁的预期对象实例,但是释放本身不会在delete []上使用BYTE*完成 - 要定义行为,您必须自定义删除器才能首先调用{{1然后~VARIABLE_SIZE_STRUCT() ...

如果您关注&#34; thunking&#34;,您可以在运行时进行检查:

delete[]

背景 - 5.2.10 / 7:

  

可以将对象指针显式转换为不同类型的对象指针。当对象指针类型的prvalue v转换为对象指针类型“指向cv T的指针”时,结果为BYTE* p; v.reset(reinterpret_cast<VARIABLE_SIZE_STRUCT*>(p = new BYTE[bytesRequired])); assert(reinterpret_cast<BYTE*>(v.get()) == p); 。将“指向T1的指针”的prvalue转换为“指向T2的指针”类型(其中T1和T2是对象类型,T2的对齐要求不比   那些T1)并返回其原始类型产生原始指针值。

因此,如果static_cast<cvT*>(static_cast<cv void*>(v))的对齐要求比VARIABLE_SIZE_STRUCT更严格,则您保证不会使用BYTE检索原始指针