Why is GoogleMock leaking my shared_ptr?

boost, c++, googlemock, googletest, shared-ptr

Solution

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();`

Problem

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`.

Original source