【问题标题】:unique_ptr with reinterpret_cast, will the structure get freed correctly?带有 reinterpret_cast 的 unique_ptr,结构会被正确释放吗?
【发布时间】:2021-08-02 15:16:42
【问题描述】:

unique_ptr 会正确释放我的动态分配结构吗?

unique_ptr<sockaddr> p;

switch (type) {
    case AF_INET:
        p.reset( reinterpret_cast<sockaddr *>(new sockaddr_in) );
        break;
    case AF_INET6:
        p.reset( reinterpret_cast<sockaddr *>(new sockaddr_in6) );
        break;
    case AF_UNIX:
        p.reset( reinterpret_cast<sockaddr *>(new sockaddr_un) );
        break;
    default:
        throw domain_error("Invalid domain");
}   

你有更好的选择吗?这是一种好的编码风格吗?每个结构有 3 个独立的 unique_ptr 而不是只有 1 个更好吗?

【问题讨论】:

  • 很难说。 sockaddr_FOO 是什么?它们是sockaddr 的子类吗?然后,只要他们有一个虚拟析构函数,C++ 就会做正确的事情,而不需要你对 base 进行丑陋的强制转换。但如果它们不是——假设它们是 Linux/POSIX 的东西,它们就不会是——那么你就拥有 UB,只需将它们提供给期望 sockaddr * 的地方。即使sockaddr_FOO 有一个sockaddr 作为第一个成员,使演员“有效”,你在摧毁他们时仍然有UB。
  • 对于任何一次只能存在一个的不相关对象类型,请参阅std::variant 或如果需要一些 C++11 反向移植。
  • 因为这看起来好像 unique_ptr 已经存在了一段时间,而您只是在“幕后”更改值,并且您使用的是普通的旧 C 数据类型:分配一个联合并分配一个成员根据type。以联合中的几个备用字节为代价节省了动态内存处理所需的大量周期。这看起来像是一个教科书示例,说明了为什么存在工会。

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


【解决方案1】:

Unique ptr 删除它的参数。将事物删除为它们未分配的类型只会在狭窄的情况下避免 UB。

我会保守一点,这样做

template<class T, class U>
auto cleanup_as=[](U* u){ delete reinterpret_cast<T*>(u);};

template<class T>
using my_up=std:unique_ptr<T,void(*)(T*)>;

template<class T, class U>
my_up<T> wrap_up_as(U*pu){
  return my_up<T>(pu, cleanup_as<U,T>);
}

那么你的代码就变成了

my_up<sockaddr> p;

switch (type) {
  case AF_INET:
    p = wrap_up_as<sockaddr>( new sockaddr_in );
    break;

等等

这里唯一 ptr 中的额外函数指针销毁器会记住结构是如何分配的,并在销毁时正确清理它。然后一些辅助胶使其易于使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2022-01-13
    • 1970-01-01
    • 2013-01-04
    • 1970-01-01
    相关资源
    最近更新 更多