为什么GoogleMock泄露我的shared_ptr? [英] Why is GoogleMock leaking my shared_ptr?

查看:1490
本文介绍了为什么GoogleMock泄露我的shared_ptr?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用GoogleMock / GoogleTest进行测试,和我看到一些奇怪的行为时有匹配一个shared_ptr了假作为参数,并期望被称为在同一个shared_ptr的。违规件code的:

 的#include< gmock / gmock.h>
#包括LT&; GTEST / gtest.h>#包括LT&;升压/ shared_ptr.hpp>
#包括LT&;升压/ make_shared.hpp>
使用名字空间boost;
使用命名空间测试;结构MyParameter
{
    虚拟〜MyParameter(){}
    虚拟无效myMethod的()= 0;
};结构MyParameterMock:公共MyParameter
{
    MOCK_METHOD0(myMethod的,无效());
};MyClass的结构
{
    虚拟〜MyClass的(){}
    虚拟无效myMethod的(shared_ptr的< MyParameter指p){}
};结构MyClassMock:公共MyClass的
{
    MOCK_METHOD1(myMethod的,无效(shared_ptr的< MyParameter>));
};TEST(LeakTest,GoogleMockLeaksMatchedPointer)
{
    shared_ptr的< MyClassMock> C = make_shared< MyClassMock>();
    shared_ptr的< MyParameterMock> P = make_shared< MyParameterMock>();
    {
        InSequence的假人;
        EXPECT_CALL(* c中,myMethod的(式(P​​)));
        EXPECT_CALL(* P,myMethod的());
    }
    C-> myMethod的(对);
    对 - > myMethod的();
}

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

  leak_ptr_mock.cpp:37:错误:此模拟对象(在测试LeakTest.GoogleMockLeaksMatchedPointer使用)应该被删除,但绝不是。它的地址是@ 0x9309544。
错误:1泄漏在程序退出时发现的模仿对象。

为什么发生这种情况的任何想法?我宁愿没有使用莫克:: AllowLeak


解决方案

这是拿着结果 P 的shared_ptr ,使用 InSequence的并在其中您已声明您的期望的顺序。

当你调用

  EXPECT_CALL(* C,myMethod的(公式(P)));

您增加 use_count P 的。为了使泄漏检测通过, P 必须在(或之前) TEST 。<结束时被销毁/ p>

这里的问题是,国内,gmock通过持有一个指向preceding预期保持所需的模拟调用序列的记录。所以,当你调用 EXPECT_CALL(* P,myMethod的()); ,它得到了指针的拷贝到previous期望

这则有呼叫阻塞到 P 的析构函数时,测试结束的效果。

为了解决这个问题,我认为最好的办法是打电话

  EXPECT_TRUE(莫克:: VerifyAndClearExpectations(p.get()));

在退出之前测试。这将清除期望 P ,其中包括至关重要的prerequisite预期,这反过来又使 P 的析构函数要正确调用。

另外,如果模拟调用的顺序是不重要的,简单地删除 InSequence的假人; 也将让 P 的析构函数来执行。



顺便说一句,你的code有几个问题;


  • 您的基础结构应该有虚析构函数

  • MyClass的:: myMethod的应该是为了虚拟允许gmock的功能来覆盖它

  • P-&GT; myMethod的(P); P-&GT; myMethod的();

I use GoogleMock/GoogleTest for testing, and I'm seeing some strange behavior when a matcher has a shared_ptr to a mock as a parameter, and EXPECT is called on the same shared_ptr. The offending piece of code:

#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();
}

When this test is run, I get

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.

Any idea of why this happens? I rather not have to use Mock::AllowLeak.

解决方案

This is a result of holding p as a shared_ptr, using InSequence and the order in which you have declared your expectations.

When you call

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

you increase the use_count of p. In order for the leak detection to pass, p must be destroyed at (or before) the end of TEST.

The problem here is that internally, gmock maintains a record of the required mock call sequence by holding a pointer to the preceding expectation. So when you call EXPECT_CALL(*p, myMethod());, it gets a copy of the pointer to the previous expectation.

This then has the effect of blocking the call to p's destructor when TEST ends.

In order to work around this, I think your best bet is to call

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

just before you exit TEST. This clears the expectations on p, including critically its prerequisite expectation, which in turn allows the destructor of p to be invoked correctly.

Alternatively, if the order of the mock calls is unimportant, simply removing InSequence dummy; will also allow p's destructor to execute.


As an aside, your code has a couple of issues;

  • Your base structs should have virtual destructors
  • MyClass::myMethod should be virtual in order to allow gmock's function to override it
  • p->myMethod(p); should be p->myMethod();

这篇关于为什么GoogleMock泄露我的shared_ptr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆