【问题标题】:Using std::make_unique with the GetProfileBinary function call将 std::make_unique 与 GetProfileBinary 函数调用一起使用
【发布时间】:2021-11-24 10:38:44
【问题描述】:

我已经看到了这个答案 (Advantages of using std::make_unique over new operator),它指出:

如果您需要自定义删除器或采用其他地方的原始指针,请不要使用make_unique

这是我的代码:

void CAutomaticBackupSettingsPage::GetLastBackupDate(COleDateTime& rBackupDate)
{
    DATE* pDatTime = nullptr;
    UINT uSize;

    theApp.GetProfileBinary(_T("Options"), _T("BackupLastBackupDate"), pointer_cast<LPBYTE*>(&pDatTime), &uSize);
    if (uSize == sizeof(DATE))
        rBackupDate = *pDatTime;
    else
        rBackupDate = COleDateTime::GetCurrentTime();

    delete[] pDatTime;
    pDatTime = nullptr;
}

代码分析给了我两个警告:

后一个警告建议我使用std::make_unique,但由于我的指针数据是从GetProfileBinary 调用返回的,并且鉴于相关问题中的陈述,这是否意味着我不应该使用std::make_unique?我承认这是我以前没有做过的事情。


GetProfileBinary的用法明确指出:

GetProfileBinary 分配一个缓冲区并在*ppData 中返回其地址。 调用者负责使用delete[]释放缓冲区。

【问题讨论】:

    标签: c++ visual-c++ mfc code-analysis


    【解决方案1】:

    pDateTime 应该是nullptrGetProfileBinary 处理分配。代码分析误以为你忘记了分配。

    在调用delete[] 之前确实需要检查是否成功。我们不能使用delete[]pDatTime,因为pDatTime 不是一个数组。但是GetProfileBinary 分配使用new BYTE[size],所以我们需要转换回BYTE

    您还可以在阅读pDatTime 之前添加NULL 检查,这可能会使代码分析变得愉快。

    if (pDatTime && uSize == sizeof(DATE))
        rBackupDate = *pDatTime;
    else
        rBackupDate = COleDateTime::GetCurrentTime();
    if(pDatTime) delete[](BYTE*)pDatTime;
    

    您可以使用std::unique_ptr&lt;BYTE[]&gt; cleanup((BYTE*)pDatTime) 进行删除,但这必须在调用GetProfileBinary 之后。

    例子:

    DATE* pDatTime = nullptr;
    GetProfileBinary(_T("Options"), _T("BackupLastBackupDate"), (LPBYTE*)(&pDatTime), &uSize);
    std::unique_ptr<BYTE[]> cleanup((BYTE*)pDatTime); //automatic delete
    
    if (pDatTime && uSize == sizeof(DATE))
        rBackupDate = *pDatTime;
    else
        rBackupDate = COleDateTime::GetCurrentTime();
    
    //pDatTime = NULL; <- Error when used with unique_ptr
    ...
    //pDatTime is deleted later, when `cleanup` goes out of scope
    

    【讨论】:

    • 谢谢@AdrianMole,我想我已经解决了,编译错误还是这样。
    • 谢谢!如果我使用您的两个调整,这些警告现在将被删除。为了防止我使用的 C 风格强制转换警告:std::unique_ptr&lt;BYTE[]&gt; cleanup(pointer_cast&lt;BYTE*&gt;(pDatTime));。问题 1:我的函数中的最后一行现在是否已过时 (pDatTime = nullptr;),因为我们正在调用此 Cleanup 方法?问题 2:在我的GetProfileBinary 调用中,我转换为LPBYTE*,但在您随后的代码建议中,我们分别使用BYTE*BYTE[]。我想这无关紧要。
    • 1:pDatTime = nullptr; 被删除后就不需要了,因为它是一个局部变量,你正在退出函数。 2:您对GetProfileBinary 的调用是正确的,应该是LPBYTE*。在另一个地方,我使用了BYTE*,这与GetProfileBinary 内部的内存分配方式有关。还要小心std::unique_ptr 的使用方式,编译器可能会进行奇怪的优化并破坏它。如果您使用它,请在您的问题中显示它。
    • @and cleanup 不是一种方法。它是std::unique_ptr&lt;BYTE[]&gt; 类型的对象。它有一个重要的析构函数,当对象超出范围时运行。它是执行资源清理的析构函数。我很困惑为什么代码分析没有将其标记为 “从未使用过的变量” 问题。
    • 这很好,使用unique_ptr...(pDatTime) 后跟pDatTime = nullptr 是错误的。但是可以把pDatTime = nullptr放在delete[]...之后,那样的话它不会完成任何事情,但也不会导致错误。见编辑。
    猜你喜欢
    • 1970-01-01
    • 2012-10-28
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 2017-03-05
    • 1970-01-01
    相关资源
    最近更新 更多