由于 GTest 拆卸,智能指针被过早删除

Smart pointer gets prematurely deleted due to GTest teardown

我目前正在重构代码以使原始指针使用智能指针并对此进行测试class但遇到过早删除智能指针的问题

这是一个例子:

class SomeObjectType
{
public:
   void init()
   {
   }
};

class Helper
{
public:
    Helper()
    {
        std::cout << "Helper constructor" << std::endl;
       //some codes
    }
    ~Helper()
    {
        std::cout << "Helper destructor" << std::endl;
       //some codes
    }
    SomeObjectType* createObject()
    {
        return new SomeObjectType;
      //some codes
    }
    void destroyObject(SomeObjectType* obj)
    {
       //some codes
    }
};

class Base
{
public:
    Base()
    {
       helper = std::make_shared<Helper>();
    }
    ~Base()
    {
       destroyObject(obj);
    }
    void Init()
    {
       obj = createObject();
    }
    SomeObjectType* createObject()
    {
       return helper->createObject();
    }
    void destroyObject(SomeObjectType* obj)
    {
       helper->destroyObject(obj); // <-- I get the error here
    }

protected:
    std::shared_ptr<Helper> helper;

private:
    SomeObjectType* obj;

FRIEND_TEST(BaseTest , Init_handleSuccess);
};

在我的测试中:

class BaseTest : public ::testing::Test
{
public:
    void SetUp()
    {
        sut_ = std::make_unique<Base>();
        helperMock_ = std::make_shared<HelperMock>();
        //helperMock_ = new HelperMock;  //it works when I dont use smart pointers but of course there is a leak here
    }

protected:
    std::unique_ptr<Base> sut_;
    std::shared_ptr<HelperMock> helperMock_;
    //HelperMock* helperMock_; //it works when I dont use smart pointers but of course there is a leak here
};

TEST_F(BaseTest, Init_handleSuccess)
{
    auto obj = new SomeObjectType();
    sut_->helper.reset(helperMock_.get());
    EXPECT_EQ(S_OK, sut_->Init());
}

当我检查日志时,我看到发生了以下情况(按此顺序):

所以基本上 helper 指针在调用 destroyObject() 之前已经被删除,因为它的生命与我的测试有关。因此,当我将测试更改为对 helper 使用原始指针时,我没有得到双重删除,但随后它变成了泄漏,因为我根本没有删除 helper :) 我该怎么做才能做到这一点当基 class 析构函数被调用时,helper 是否仍然存在?

注意:在助手的 createObject 中我需要一些 API 调用,这就是我嘲笑它的原因。我不能将 helper 作为依赖项注入,这就是为什么我必须 'hack' 它与 sut_->helper.reset(helperMock_.get());

我相信这可能是您的问题...

sut_->helper.reset(helperMock_);

我什至不确定上面的代码是如何编译的,因为我认为 reset 期望 shared_ptr 的原始指针获得所有权。 (正如您在评论中更新的那样:您实际上是在使用 .get() 调用重置)。

使用 shared_ptr 可能犯的最大错误是调用 .get() 或使用 * 运算符 - 并传递返回的原始指针以初始化另一个 shared_ptr。现在你在同一个对象上有两个不同的引用计数会话。哪一组 shared_ptr 实例首先消失将删除该对象。让另一组 shared_ptr 引用一个已删除的对象。

将上面的替换为:

sut_->helper = helperMock_;

我假设 HelperMock 派生自 Helper。