【问题标题】:Why is GoogleMock leaking my shared_ptr?为什么 GoogleMock 会泄露我的 shared_ptr?
【发布时间】:2012-05-04 10:00:29
【问题描述】:

我使用 GoogleMock/GoogleTest 进行测试,当匹配器将 shared_ptr 作为模拟参数并在同一个 shared_ptr 上调用 EXPECT 时,我看到了一些奇怪的行为。有问题的代码:

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace boost;
using namespace testing;

struct MyParameter
{
    virtual ~MyParameter() {}
    virtual void myMethod() = 0;
};

struct MyParameterMock : public MyParameter
{
    MOCK_METHOD0(myMethod, void());
};

struct MyClass
{
    virtual ~MyClass() {}
    virtual void myMethod(shared_ptr<MyParameter> p) {}
};

struct MyClassMock : public MyClass
{
    MOCK_METHOD1(myMethod, void(shared_ptr<MyParameter>));
};

TEST(LeakTest, GoogleMockLeaksMatchedPointer)
{
    shared_ptr<MyClassMock> c = make_shared<MyClassMock>();
    shared_ptr<MyParameterMock> p = make_shared<MyParameterMock>();
    {
        InSequence dummy;
        EXPECT_CALL(*c, myMethod(Eq(p)));
        EXPECT_CALL(*p, myMethod());
    }
    c->myMethod(p);
    p->myMethod();
}

当这个测试运行时,我得到

leak_ptr_mock.cpp:37: ERROR: this mock object (used in test LeakTest.GoogleMockLeaksMatchedPointer) should be deleted but never is. Its address is @0x9309544.
ERROR: 1 leaked mock object found at program exit.

知道为什么会发生这种情况吗?我宁愿不用Mock::AllowLeak

【问题讨论】:

    标签: c++ boost shared-ptr googletest googlemock


    【解决方案1】:

    这是将p 保留为shared_ptr 的结果,使用InSequence 和您声明期望的顺序。

    当你打电话时

        EXPECT_CALL(*c, myMethod(Eq(p)));
    

    您增加了puse_count。为了让泄漏检测通过,p 必须在TEST 结束时(或之前)销毁。

    这里的问题是,在内部,gmock 通过持有指向前面期望的指针来维护所需的模拟调用序列的记录。所以当你调用EXPECT_CALL(*p, myMethod());时,它会得到一份指向之前期望的指针。

    这会在TEST 结束时阻止对p 的析构函数的调用。

    为了解决这个问题,我认为你最好的选择是跟注

        EXPECT_TRUE(Mock::VerifyAndClearExpectations(p.get()));
    

    就在您退出 TEST 之前。这清除了对p 的期望,包括关键的先决条件期望,这反过来又允许正确调用p 的析构函数。

    或者,如果模拟调用的顺序不重要,只需删除InSequence dummy; 也将允许p 的析构函数执行。


    顺便说一句,您的代码有几个问题;

    • 你的基础结构应该有虚拟析构函数
    • MyClass::myMethod 应该是虚拟的,以允许 gmock 的函数覆盖它
    • p-&gt;myMethod(p); 应该是 p-&gt;myMethod();

    【讨论】:

    • 它有效,弗雷泽!我也根据您的建议更正了代码。
    • @bruno nery:您使用的是哪个版本的 GoogleMock?
    • 如果 p 在 c 之前创建会发生什么?不会比最后 c 被销毁,它的期望得到验证和清除,这将导致 p 的引用计数器递减。之后 p 将被销毁、验证并完全销毁,因为计数器现在为 0。
    • @Martin 不,由于使用了InSequence dummy;,构造顺序不会影响检查顺序。交换EXPECT_CALLs 的顺序将允许测试成功退出而不会泄漏,但如果期望的顺序无关紧要,那么您也根本不使用InSequence。顺便说一句,我正在使用 gmock 1.6.0。
    • 如果p 是一个结构会发生什么?
    猜你喜欢
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 2011-05-02
    • 2012-11-06
    • 1970-01-01
    相关资源
    最近更新 更多