我目前正在重构代码,以使原始指针使用智能指针,并对该类进行测试,但仍然存在智能指针被过早删除的问题
这里是一个例子:
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());
答案 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。