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

Voi*_*tar 11 c++ pointers unique-ptr reinterpret-cast c++11

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

例:

std::unique_ptr<VARIABLE_SIZE_STRUCT[]> v; 
v.reset(reinterpret_cast<VARIABLE_SIZE_STRUCT*>(new BYTE[bytesRequired]));
Run Code Online (Sandbox Code Playgroud)

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

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

Col*_*nee 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);
Run Code Online (Sandbox Code Playgroud)

在这一点上,你可能最好创建自己的包装器而不是使用unique_ptr.

  • *“标准保证,如果您重新解释_cast为其他类型,然后返回到原始类型,则您将获得原始值。” *-在5.2.10 / 7中,只有在`VARIABLE_SIZE_STRUCT`对齐要求不严格的情况下才能保证比`BYTE`,这很可能是不正确的。无论如何,它将适用于大多数体系结构,但不能由标准保证。 (2认同)

Ton*_*roy 5

  • 您的分配可能没有所需的对齐方式 VARIABLE_SIZE_STRUCT

  • 分配的内存中没有放置VARIABLE_SIZE_STRUCT的对象new- 假设你处理它,unique_ptr默认的析构函数逻辑应该找到要破坏的预期对象实例,但是释放本身就不会delete []BYTE*-有定义的行为,你不得不自定义删除器调用第一~VARIABLE_SIZE_STRUCT(),然后delete[]...

如果您担心"thunking",可以在运行时进行检查:

BYTE* p;
v.reset(reinterpret_cast<VARIABLE_SIZE_STRUCT*>(p = new BYTE[bytesRequired]));
assert(reinterpret_cast<BYTE*>(v.get()) == p);
Run Code Online (Sandbox Code Playgroud)

背景 - 5.2.10/7:

可以将对象指针显式转换为不同类型的对象指针.当对象指针类型的prvalue v被转换为对象指针类型"指向cv T的指针"时,结果为static_cast<cvT*>(static_cast<cv void*>(v)).将"指向T1的指针"类型的prvalue转换为"指向T2的指针"类型(其中T1和T2是对象类型,T2的对齐要求不比T1更严格)并返回其原始类型会产生原始类型指针值.

因此,如果对齐要求VARIABLE_SIZE_STRUCT比更严格BYTE,则无法保证使用检索原始指针reinterpret_cast<BYTE*>.

  • @VoidStar你可以使用std :: is_pod作为static_assert来排除这种情况,否则我同意Tony D,新的安置会更安全. (2认同)