由于GTest崩溃,智能指针被过早删除

时间:2019-07-18 08:27:22

标签: c++ pointers googletest gmock

我目前正在重构代码,以使原始指针使用智能指针,并对该类进行测试,但仍然存在智能指针被过早删除的问题

这里是一个例子:

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的构造函数

  • 测试拆卸

  • Helper析构函数称为

  • 基本析构函数

  • 基本析构函数尝试访问已删除的helper =崩溃!

因此基本上helper指针在调用destroyObject()之前已经被删除,因为它的寿命与我的测试有关。因此,当我更改测试以对helper使用原始指针时,我没有得到双重删除,但是由于我根本没有删除helper,因此它变成了泄漏:)我该怎么办?调用基类析构函数时,helper仍然有效吗?

注意:我需要在助手的createObject中进行一些API调用,这就是我嘲笑它的原因。我无法将帮助程序作为依赖项注入,这就是为什么我必须使用sut_->helper.reset(helperMock_.get());

对其进行“破解”的原因

1 个答案:

答案 0 :(得分:1)

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

sut_->helper.reset(helperMock_);

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

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

仅用以下内容替换上面的内容:

sut_->helper = helperMock_;

我假设HelperMock来自Helper。