当使用GoogleMock和Boost::Shared Pointers时,泄露了模拟对象

8
对于这个特殊的场景,我无法消除泄漏。
执行测试时,我收到了关于Mock对象泄漏的消息。具体消息如下:
ClassElementFixture.h:102: 错误:应该删除此模仿对象(在测试ClassElementFixture.initialize中使用),但从未删除。它的地址为@0x940a650。
我标记了错误所指向的行。以下是我代码的简化版本:
...
class ClassElementFixture: public ::testing::Test
{
    public:
        boost::shared_ptr<fesa::ClassElement> classElement_;
        boost::shared_ptr<fesa::DeviceElementMock> deviceElement_;

        ...

        void SetUp()
        {
            classElement_.reset(new fesa::ClassElement());
        }

        void TearDown()
        {
        }

        void initializeFake()
        {
            fesa::ParserElementFactoryMock factory;
            deviceElement_.reset(new fesa::DeviceElementMock());

            EXPECT_CALL(factory, createDeviceElement(_))
                        .WillOnce(Return(deviceElement1_));
            EXPECT_CALL(*deviceElement_, initialize(_));//Error refers to here

            classElement_->initialize(factory);

            EXPECT_TRUE(Mock::VerifyAndClearExpectations(deviceElement_.get()));
        }
}

我已经找到了一个与之相关的问题,地址为Why is GoogleMock leaking my shared_ptr?,但那里的建议并没有解决我的问题 :X。
我唯一找到的可能解决错误的方法是:
Mock::AllowLeak(deviceElement_.get());

然而,这并不是一个很干净的解决方案=)
那么如何正确地消除泄漏呢?

我使用的是google-mock v1.6.0和google-test v1.6.0。 - Alex
5
你尝试过在TearDown()中重置shared_ptrs吗? - Arne Mertz
2
你的 shared_ptr 关系中是否存在循环?shared_ptr 存在已知问题,循环可能导致内存泄漏。 - Chris Hayden
我刚看到你的评论...对于我的长时间响应时间感到抱歉(我必须启用电子邮件通知)。自从我发布这个问题以来,使用的类的实现已经改变了。所以我现在无法再重现这个错误了:X 我刚刚移除了所有的Mock::AllowLeak,现在一切都正常工作了。我认为这可能是由于循环依赖引起的...像这样的东西在旧代码中被使用,所以无论如何,感谢您的帮助! - Alex
3个回答

3
如果使用智能指针,您仍然需要清楚地了解所有权,否则可能会出现性能差、循环依赖和内存泄漏问题。
我建议默认选择独占所有权的智能指针应为unique_ptr,并使用原始指针作为观察者。
如果观察者可能会超过所有者的生命周期,那么将所有者移动到一个shared_ptr中,而将观察者移动到weak_ptr中。
只在没有明确所有者时才使用"shared"shared_ptr,并注意循环依赖。

2

这是一个老问题,但我没看到有人提到我刚刚发现的解决方案。

我看到了相同的错误,直到我在我模拟的类中添加了虚析构函数。在您的情况下,请确保ParserElementFactoryMock上有虚析构函数。如果没有虚析构函数,模拟对象将不会在超出作用域时释放资源,所以这是有道理的。


2

不要使用共享指针。如果你确实需要使用它们,请确保它们返回到0并在测试结束时被销毁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接