由于 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
= 崩溃!
所以基本上 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。
我目前正在重构代码以使原始指针使用智能指针并对此进行测试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
= 崩溃!
所以基本上 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。