【问题标题】:Do not delete a raw pointer that is not an owner<T> (i.11)不要删除不是 owner<T> 的原始指针 (i.11)
【发布时间】:2018-11-02 18:13:05
【问题描述】:

我试图尝试五/三/零的规则。在编译我的程序时,我收到了一个警告 C26401,说我必须不要删除我不拥有的指针,这在析构函数的 delete[] pChar_; 行中。

我同意我在调用move ctor 时特别有问题,当我在调用源对象时应用std::swap 时。

那么我该如何纠正这个问题呢?

编辑:正如评论中所建议的,我可能会使用 std::string (Good) 但我想知道如何在不修改类型的情况下解决问题让我们说学到了:)

using namespace std;

struct A
{

  A();
  A(int Int, const char* pChar);

  A(const A& rhs);
  A& operator=(A rhs);

  A(A&& rhs);

  ~A();

  void swap(A& rhs);
  int Int_ = 0;
  char *pChar_ = nullptr;
};

A::~A()
{
    std::cout << "----DTOR----" << std::endl;

    if (pChar_ != nullptr)
    {
        delete[] pChar_;
        pChar_ = nullptr;
    }
}

A::A(int Int, const char* pChar) :
     Int_(Int), pChar_(new char[strlen(pChar) + 1])
{
    strncpy_s(pChar_, strlen(pChar) + 1, pChar, _TRUNCATE);
}

A::A(const A& rhs) : A(rhs.Int_, rhs.pChar_) {}

A& A::operator=(A rhs)
{   
    swap(rhs);
    return *this;
}

A::A(A&& rhs)
{
    swap(rhs);
}

void A::swap(A& rhs)    
{
    std::swap(this->Int_, rhs.Int_);
    std::swap(this->pChar_, rhs.pChar_);
}

int main()
{
    A v1{ 1, "Hello" }; 
    {
        A v3{ std::move(v1) };
    }
}

【问题讨论】:

  • 用std::string替换你的char*,你可以回到零规则。
  • @CoryKramer :是的,这是我想用的,但我想知道是否有办法在不使用 std::string 的情况下解决这个问题,只是为了了解如何解决这种情况。
  • 我没有看到代码有问题。 FWIW if (pChar_ != nullptr) 检查是不需要的,因为 nullptr 上的 delete 是非操作
  • 我依稀记得GSL中的一些owner&lt;Ptr&gt;标签。
  • @chris :很好,我在指南中读到了这一点,但显示的示例类似于 owner 用于返回指针的函数,但这不是我的情况,你能解释一下我该如何使用这个主人!?!

标签: c++ move-semantics


【解决方案1】:

我没有 VS 的副本可以重现您的警告,但在我看来,警告来自 CPP Code Guidelines,特别是 I.11: Never transfer ownership by a raw pointer (T*) or reference (T&):

执法

  • (简单)在删除不是owner&lt;T&gt; 的原始指针时发出警告。建议使用标准库资源句柄或使用owner&lt;T&gt;。

所以解决方案是使用gsl::owner&lt;char *&gt; pChar_ = nullptr;。请注意,gsl::owner 只不过是帮助代码读者(人类或工具)的注释,不会神奇地使您的代码安全。

据我所知,您的代码看起来不错。


我遇到的一个问题是 ctor:

A(int Int, const char* pChar) :
    Int_(Int), pChar_(new char[strlen(pChar) + 1])
{
    strncpy_s(pChar_, strlen(pChar) + 1, pChar, _TRUNCATE);
}

这是伪装成安全的不安全代码。 strncpy_s 给你安全感。但实际上它在您的代码中绝对没有任何作用(为了安全起见)。因为如果pChar 有问题(例如,它不指向以空结尾的字符串),那么strlen 将首先失败。因此,要么说出每个 std 函数所说的内容:pChar 应该是一个指向以空字符结尾的字符串的有效指针,否则算作 UB,或者保护 strlen。一旦你在 strlen 守卫,那么strcpy 就足够了。

您也没有检查Int 是否等于strlen。他们应该是。

【讨论】:

    猜你喜欢
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    相关资源
    最近更新 更多