在测试中使用 unique_ptr 时出现无效指针错误

Posted

技术标签:

【中文标题】在测试中使用 unique_ptr 时出现无效指针错误【英文标题】:Invalid pointer error when using unique_ptr in tests 【发布时间】:2019-04-07 15:33:35 【问题描述】:

我有一个将std::unique_ptr<uint8_t[]> 作为输入并对其进行处理的方法。在我的单元测试中,

以下是我创建和初始化此参数的方式:(在 stack 上)

uint8_t testBytes[] = 1, 2, 3, 4;
std::unique_ptr<uint8_t[]> testBytesPtr = std::make_unique<uint8_t[]>(4);
testBytesPtr.reset(testBytes);

并将其传递给方法,如:

myClass.processData(std::move(testBytesPtr));

在我的单元测试结束时,我收到以下错误消息:

free():无效指针:0xbed6b8c0


这是我的单元测试的样子:

#include "gtest.h"
#include "gmock.h" // for some deps

//...

TEST(MyClassUnittests, test1) 
    // Initializing the byte array.
    uint8_t testBytes[] = 1, 2, 3, 4;
    std::unique_ptr<uint8_t[]> testBytesPtr = std::make_unique<uint8_t[]>(4);
    testBytesPtr.reset(testBytes);

    EXPECT_TRUE(myClass.processData(std::move(testBytestPtr));

我还应该注意,如果testBytes上初始化(例如uint8_t* testBytes = new uint8_t()),错误信息变为

双重释放或损坏(fasttop):0xb75c1e18

非常感谢任何帮助。

【问题讨论】:

unique_ptr 指向自动存储中的对象而不提供无操作删除器是一个坏主意。不要删除堆栈。 如果不是新的,请不要删除。 提供的 sn-p 是我的单元测试的全部内容。我没有明确删除任何内容,所以我不确定如何避免 implicit 删除。 @MatinKh unique_ptr 析构函数 delete[] 是默认保持的指针,除非您提供不同的 deleter 【参考方案1】:

delete []-ing 不属于new []-ed 的东西,也不是你拥有的,是严重禁忌的。

看看这些行:

uint8_t testBytes[] = 1, 2, 3, 4;
std::unique_ptr<uint8_t[]> testBytesPtr = std::make_unique<uint8_t[]>(4);
testBytesPtr.reset(testBytes);

删除不相关的临时动态分配叶:

uint8_t testBytes[] = 1, 2, 3, 4;
std::unique_ptr<uint8_t[]> testBytesPtr(testBytes);

当 dtor 启动时会导致未定义行为。

诚然,您移动了一次std::unique_ptr,但这只是改变了爆炸发生的确切点。

考虑到您要测试的功能,试试这个以获得正确分配的测试数据副本:

uint8_t testBytes[] = 1, 2, 3, 4;
auto testBytesPtr = std::make_unique<uint8_t[]>(std::size(testBytes));
std::copy(std::begin(testBytes), std::end(testBytes), &testBytesPtr[0]);

【讨论】:

感谢您解释问题所在。但是,我仍然不清楚如何解决这个问题。我没有明确地delete[] 任何东西,该方法只读取数据。你能澄清一下解决方案吗? 添加了如何获取正确分配的测试数据副本。 @MatinKh: unique_ptr 在其指针被销毁时调用 delete。这就是unique_ptr 的全部目的。因此,如果您没有通过newmake_unique 创建指针,则不要将其存储在unique_ptr 中。 我不认为将数据复制到 unique_ptr 会解决问题。我收到此错误:double free or corruption (fasttop): 0xb87b73a0,无论我是否复制数据。仅这一行 auto testBytesPtr = std::make_unique&lt;uint8_t[]&gt;(...); 就给了我错误。 那行是无害的,它只是创建了一个拥有一块新内存的 unique_ptr。但是.reset(somelocal) 不好。

以上是关于在测试中使用 unique_ptr 时出现无效指针错误的主要内容,如果未能解决你的问题,请参考以下文章

free():在 unique_ptr 上使用 get() 而不是 release() 时指针无效

使用 std::unique_ptr.reset() 更改指针下的对象

设置沙盒测试员帐户时出现“无效年份”错误

在 Java 中测试时出现空指针异常

在指针迭代中使用 for 循环时出现分段错误

为啥我在将 unique_ptr 返回给模板类的对象的函数定义时出现错误?