Why does Google Test/Mock show leaked mock object error by std::unique_ptr?
Asked Answered
T

1

12

Let's assume that there is Bar object which uses a Foo object. The ownership is exclusive, so Bar gets Foo as a std::unique_ptr in its constructor. I would like to test Bar with Google Test framework, so I made a following code:

using namespace testing;

class Foo
{
  public:
    virtual int F() = 0;
};

class Bar
{
  public:
    Bar(std::unique_ptr<Foo>&& foo) : m_foo(std::move(foo))
    {
    }

    int B()
    {
        return m_foo->F();
    }

  private:
    std::unique_ptr<Foo> m_foo;
};

class MockFoo : public Foo
{
  public:
    MOCK_METHOD0(F, int());
};

class BarTest : public Test
{
};

TEST_F(BarTest, Test1)
{
    auto mock_foo = std::make_unique<MockFoo>();
    ON_CALL(*mock_foo, F()).WillByDefault(Return(1));

    Bar bar(std::move(mock_foo));

    auto val = bar.B();

    EXPECT_THAT(val, 1);
}

The test runs well but I got the following error:

...test.cpp:293: ERROR: this mock object (used in test BarTest.Test1) should be deleted but never is. Its address is @0x1c7c590. ERROR: 1 leaked mock object found at program exit.

I think Google Test thinks that I have not destroyed mock_foo but it does not see that it does not have to be deleted here because it has been moved. The test is safe because the object itself is the same, just the ownership has changed (which is my intention).

Is my assumption correct? If yes, how can I suppress this error message? I no, where is the memory leak?

Terpsichorean answered 23/5, 2018 at 18:54 Comment(1)
@Justin Yes, it does, thanks a lot. Can you please add this as an answer to be able to accept it?Chieftain
H
17

The problem is that Foo does not have a virtual destructor. std::unique_ptr<Foo> thus won't be calling the derived class's destructor, just Foo's destructor.

class Foo
{
  public:
    virtual ~Foo() = default;
    virtual int F() = 0;
};

See When to use virtual destructors? If a base class Foo has virtual functions, it should either have a virtual destructor or a non-public destructor.

Hatbox answered 23/5, 2018 at 19:18 Comment(2)
@Thanks, this was the solution. What I do not understand it, why does it work if everything is the same but Bar receives pure pointer (Foo*)? The situation should be the same but the error message does not occur.Chieftain
@TiborTakács Unfortunately, I don't know how googletest's leak checking works. Assuming you wrote new MockFoo, if you did write delete m_foo, that would be Undefined Behavior. If you didn't write new, but wrote smth like MockFoo mock_foo then passed in &mock_foo, then that's completely expectedHatbox

© 2022 - 2024 — McMap. All rights reserved.