Valgrind report definitely loss in EXPECT_CALL

614 views
Skip to first unread message

paolo achdjian

unread,
Nov 16, 2010, 3:57:47 AM11/16/10
to Google C++ Mocking Framework
Hi,
I'm using valgrind to catch memory managment problems.
I noticed that sometime the valgrind report a definitely loss memory
in the code generate by the EXPECT_CALL macro.

What I don't undersand is why only some declarations loss memory.
For example, in the following function, only the second EXPECTA_CALL
has a memory loss; the others are right and all are satisfied.

TEST_F(TestDetectUDPStream,stream_is_not_present){
const int UDPPacketSize=1368;
const long long startTime = 12543535;

{
InSequence dummy;
EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime));
EXPECT_CALL(*mockUDPSocket,
recv(_,_)).WillOnce(Return(UDPPacketSize));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime +
DetectUDPStream::C_Timeout-1 ));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime +
DetectUDPStream::C_Timeout ));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

}

ASSERT_THAT(toTest->streamPresent(),true);
ASSERT_THAT(toTest->streamPresent(),true);
ASSERT_THAT(toTest->streamPresent(),false);
}

Martin Svensson

unread,
Nov 16, 2010, 4:17:31 AM11/16/10
to paolo achdjian, Google C++ Mocking Framework
What is the valgring message, and what does the function signature and
calling code look like?

/Martin Svensson

paolo achdjian

unread,
Nov 16, 2010, 5:50:46 AM11/16/10
to Google C++ Mocking Framework
Hi Martin,

following there are a test code
I compiled it using:
gcc testMock.cpp -lgmock -lgtest -lpthread -o testMock -g3

and check using valgrind:



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

using ::testing::_;
using ::testing::Return;
using ::testing::InSequence;
using ::testing::Mock;



int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}


class UDPSocket {
public:
UDPSocket() {}
virtual ~UDPSocket() {}

virtual bool open(int port){return true;}
virtual bool close(){return true;}
virtual int recv(unsigned char * buffer, unsigned int maxSize){return
0;}
};

class stb_time {
public:
virtual long long stb_timeMsecLongLong(){return 0;};
};


class DetectUDPStream {
public:
DetectUDPStream(int port);
virtual ~DetectUDPStream();
bool streamPresent();

void setUDPSocket(UDPSocket *);
void setStbTime(stb_time *);
public:
static const int C_Timeout = 100;
static const int C_MaxDataSocket = 32768;

private:
UDPSocket * udpSocket;
stb_time * stbTime;
long long lastTime;
int udpPort;
};


DetectUDPStream::DetectUDPStream(int port) {
udpSocket = new UDPSocket;
stbTime = new stb_time;
lastTime = -1;

udpSocket->open(port);
udpPort = port;
}

DetectUDPStream::~DetectUDPStream() {
delete udpSocket;
delete stbTime;

}



inline void DetectUDPStream::setUDPSocket(UDPSocket * newSocket){
delete udpSocket;
udpSocket = newSocket;
udpSocket->open(udpPort);
}


inline void DetectUDPStream::setStbTime(stb_time * newTime){
delete stbTime;
stbTime = newTime;
}

bool DetectUDPStream::streamPresent(){

bool isStreamPresent = false;
long long time;

unsigned char data[C_MaxDataSocket];

time = stbTime->stb_timeMsecLongLong();
if (lastTime == -1) {
lastTime = time;
}
if (udpSocket->recv(data,C_MaxDataSocket) > 0) {

isStreamPresent = true;
lastTime = time;
} else {
if ( (time - lastTime) < C_Timeout){
isStreamPresent = true;
}
}


return isStreamPresent;
}


class TestDetectUDPStream : public ::testing::Test {
public:
class MockUDPSocket : public UDPSocket{
public:
MOCK_METHOD1(open, bool(int port));
MOCK_METHOD0(close, bool());
MOCK_METHOD2(recv, int(unsigned char * buffer, unsigned int
maxSize));
};

class Mockstb_time : public stb_time {
public:
MOCK_METHOD0(stb_timeMsecLongLong, long long());
};

public:
void SetUp();
void TearDown();
protected:
DetectUDPStream * toTest;
Mockstb_time * mockstb_time;
MockUDPSocket * mockUDPSocket;
static const int portToTest = 1234;

};


void TestDetectUDPStream::SetUp() {
mockUDPSocket = new MockUDPSocket;
EXPECT_CALL(*mockUDPSocket,
open(portToTest)).WillOnce(Return(true));

mockstb_time = new Mockstb_time;


toTest = new DetectUDPStream(portToTest);
toTest->setUDPSocket(mockUDPSocket);
toTest->setStbTime(mockstb_time);
Mock::AllowLeak(mockstb_time);
}

void TestDetectUDPStream::TearDown() {
delete toTest;
}

TEST_F(TestDetectUDPStream,stream_is_not_present){
const int UDPPacketSize=1368;
const long long startTime = 12543535;

{
InSequence dummy;
EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime));
EXPECT_CALL(*mockUDPSocket,
recv(_,_)).WillOnce(Return(UDPPacketSize));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime +
DetectUDPStream::C_Timeout-1 ));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime +
DetectUDPStream::C_Timeout ));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

}

ASSERT_THAT(toTest->streamPresent(),true);
ASSERT_THAT(toTest->streamPresent(),true);
ASSERT_THAT(toTest->streamPresent(),false);
}

TEST_F(TestDetectUDPStream,stream_is_present){
const int UDPPacketSize=1368;
const long long startTime = 12543535;
const long long time1 = startTime+DetectUDPStream::C_Timeout/3;
const long long time2 = time1+DetectUDPStream::C_Timeout/3;
const long long time3 = startTime+DetectUDPStream::C_Timeout;
const long long time4 = time2+DetectUDPStream::C_Timeout;

{
InSequence dummy;
EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime));
EXPECT_CALL(*mockUDPSocket,
recv(_,_)).WillOnce(Return(UDPPacketSize));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(time1 ));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(time2));
EXPECT_CALL(*mockUDPSocket,
recv(_,_)).WillOnce(Return(UDPPacketSize));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(time3));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(time4 ));

paolo achdjian

unread,
Nov 16, 2010, 5:54:17 AM11/16/10
to Google C++ Mocking Framework
I'm sorry, but I press a key that sent the unfinished message.

As I writing, I check the code using valgrind:
valgrind --leak-check=full --num-callers=24 ./testMock

and it reports:

in use at exit: 7,498 bytes in 124 blocks
==13257== total heap usage: 800 allocs, 676 frees, 102,428 bytes
allocated
==13257==
==13257== 2,655 (312 direct, 2,343 indirect) bytes in 1 blocks are
definitely lost in loss record 123 of 124
==13257== at 0x4C27CC1: operator new(unsigned long)
(vg_replace_malloc.c:261)
==13257== by 0x40EC8E: testing::internal::FunctionMockerBase<int ()
(unsigned char*, unsigned int)>::AddNewExpectation(char const*, int,
std::string const&, std::tr1::tuple<testing::Matcher<unsigned char*>,
testing::Matcher<unsigned int> > const&) (gmock-spec-builders.h:1477)
==13257== by 0x40A143: testing::internal::MockSpec<int ()(unsigned
char*, unsigned int)>::InternalExpectedAt(char const*, int, char
const*, char const*) (gmock-spec-builders.h:1213)
==13257== by 0x404256:
TestDetectUDPStream_stream_is_not_present_Test::TestBody()
(testMock.cpp:160)
==13257== by 0x506A939: testing::Test::Run() (gtest.cc:2095)
==13257== by 0x506AA47: testing::internal::TestInfoImpl::Run()
(gtest.cc:2314)
==13257== by 0x506AB0C: testing::TestCase::Run() (gtest.cc:2420)
==13257== by 0x506E4C3:
testing::internal::UnitTestImpl::RunAllTests() (gtest.cc:4024)
==13257== by 0x403B32: main (testMock.cpp:15)
==13257==
==13257== 4,843 (312 direct, 4,531 indirect) bytes in 1 blocks are
definitely lost in loss record 124 of 124
==13257== at 0x4C27CC1: operator new(unsigned long)
(vg_replace_malloc.c:261)
==13257== by 0x40EC8E: testing::internal::FunctionMockerBase<int ()
(unsigned char*, unsigned int)>::AddNewExpectation(char const*, int,
std::string const&, std::tr1::tuple<testing::Matcher<unsigned char*>,
testing::Matcher<unsigned int> > const&) (gmock-spec-builders.h:1477)
==13257== by 0x40A143: testing::internal::MockSpec<int ()(unsigned
char*, unsigned int)>::InternalExpectedAt(char const*, int, char
const*, char const*) (gmock-spec-builders.h:1213)
==13257== by 0x404C3F:
TestDetectUDPStream_stream_is_present_Test::TestBody() (testMock.cpp:
186)
==13257== by 0x506A939: testing::Test::Run() (gtest.cc:2095)
==13257== by 0x506AA47: testing::internal::TestInfoImpl::Run()
(gtest.cc:2314)
==13257== by 0x506AB0C: testing::TestCase::Run() (gtest.cc:2420)
==13257== by 0x506E4C3:
testing::internal::UnitTestImpl::RunAllTests() (gtest.cc:4024)
==13257== by 0x403B32: main (testMock.cpp:15)
==13257==
==13257== LEAK SUMMARY:
==13257== definitely lost: 624 bytes in 2 blocks
==13257== indirectly lost: 6,874 bytes in 122 blocks
==13257== possibly lost: 0 bytes in 0 blocks
==13257== still reachable: 0 bytes in 0 blocks
==13257== suppressed: 0 bytes in 0 blocks


Regards,
Paolo

Martin Svensson

unread,
Nov 16, 2010, 6:24:41 AM11/16/10
to paolo achdjian, Google C++ Mocking Framework
On 2010-11-16 11:54, paolo achdjian wrote:
> valgrind --leak-check=full --num-callers=24 ./testMock
>
Try using "--track-origins=true" too.

/Martin

paolo achdjian

unread,
Nov 16, 2010, 6:39:12 AM11/16/10
to Google C++ Mocking Framework
Hi Martin,

there are any changes on the report.

On the other hand, that option it's usefull only for uninitializated
values.
But in this case it seems to me that thare are somes objects not
freed.

Regards,
Paolo

On Nov 16, 12:24 pm, Martin Svensson

Vlad Losev

unread,
Nov 16, 2010, 9:51:44 AM11/16/10
to paolo achdjian, Google C++ Mocking Framework
Paolo,

It looks like your tests leak TestDetectUDPStream::mockstb_time and TestDetectUDPStream:: mockUDPSocket. If they are indeed leaked, you will see a lot of associated leaks. Why don't you make these objects direct members instead of pointers?
Regards,
Vlad

paolo achdjian

unread,
Nov 16, 2010, 10:19:18 AM11/16/10
to Google C++ Mocking Framework
Hi Vlad,

the two mock objects are deleted in the destructor of the class to
test: DetectUDPStream.

And it's for this reason I must create explicitally these two mock
objects, otherwise the destructor of DetectedUDPStream will try to
deallocated a pointer not allocated.

Regards,
Paolo

Vlad Losev

unread,
Nov 16, 2010, 12:42:22 PM11/16/10
to paolo achdjian, Google C++ Mocking Framework
On Tue, Nov 16, 2010 at 7:19 AM, paolo achdjian <pach...@gmail.com> wrote:
Hi Vlad,

the two mock objects are deleted in the destructor of the class to
test: DetectUDPStream.

And it's for this reason I must create explicitally these two mock
objects, otherwise the destructor of DetectedUDPStream will try to
deallocated a pointer not allocated.

If an stb_time pointer is being deleted in DetectUDPStream's destructor, why do you have to call Mock::AllowLeak() on it?  

paolo achdjian

unread,
Nov 17, 2010, 3:17:54 AM11/17/10
to Google C++ Mocking Framework
Hi Vlad,


> If an stb_time pointer is being deleted in DetectUDPStream's destructor, why
> do you have to call Mock::AllowLeak() on it?

This will be the subject of another interesting thread.
If I don't tell to the google mock library to doesn't check that
pointer, the library warn that isn't deleted, also, as you can see,
it's deleted in the destructor.

The strange thing is that the pointers mockstb_time and mockUDPSocket
have the same livecycle and all are used into EXPECT_CALL but only
mockstb_time are reported as not deleted !

In any way, if I don't use Mock::AllowLeak(mockstb_time), the behviour
grown worse: there are more objects not deleted.

Regards,
Paolo

Vlad Losev

unread,
Nov 17, 2010, 4:08:22 AM11/17/10
to paolo achdjian, Google C++ Mocking Framework
Then it may be the matter of you mixing setting of expectations on your mocks and making calls to them. Google Mock requires the expectations must be set on a mock before the first call to it is made.

paolo achdjian

unread,
Nov 17, 2010, 4:51:01 AM11/17/10
to Google C++ Mocking Framework
Hi Vlad,

all my expectations are created before the call of the funcion to
test !

Anyway, I empty the SetUp method and modified the code as reported
follow, but the problem remains:
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(UDPPacketSize))
produce an objects the isn't deleted.

regards,
Paolo


TEST_F(TestDetectUDPStream,stream_is_not_present){
const int UDPPacketSize=1368;
const long long startTime = 12543535;

mockUDPSocket = new MockUDPSocket;
mockstb_time = new Mockstb_time;
EXPECT_CALL(*mockUDPSocket,
open(portToTest)).WillOnce(Return(true));




Mock::AllowLeak(mockstb_time);

{
InSequence dummy;
EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime));
EXPECT_CALL(*mockUDPSocket,
recv(_,_)).WillOnce(Return(UDPPacketSize));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime +
DetectUDPStream::C_Timeout-1 ));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

EXPECT_CALL(*mockstb_time,
stb_timeMsecLongLong()).WillOnce(Return(startTime +
DetectUDPStream::C_Timeout ));
EXPECT_CALL(*mockUDPSocket, recv(_,_)).WillOnce(Return(0));

}

toTest = new DetectUDPStream(portToTest);
toTest->setUDPSocket(mockUDPSocket);
toTest->setStbTime(mockstb_time);


ASSERT_THAT(toTest->streamPresent(),true);
ASSERT_THAT(toTest->streamPresent(),true);
ASSERT_THAT(toTest->streamPresent(),false);
}


On Nov 17, 10:08 am, Vlad Losev <v...@losev.com> wrote:
> Then it may be the matter of you mixing setting of expectations on your
> mocks and making calls to them. Google Mock requires the expectations must
> be set on a mock before the first call to it is made.
>

Vlad Losev

unread,
Nov 17, 2010, 10:30:28 AM11/17/10
to paolo achdjian, Google C++ Mocking Framework
I think I see the problem now. Mockstb_time doesn't have a virtual destructor.

On Wed, Nov 17, 2010 at 1:51 AM, paolo achdjian <pach...@gmail.com> wrote:
Hi Vlad,

all my expectations are created before the call of the funcion to
test !

The call toTest->setUDPSocket(mockUDPSocket) in SetUp() is invoking methods of mockUDPSocket before expectations are being set in the test body.

Zhanyong Wan (λx.x x)

unread,
Nov 17, 2010, 10:42:03 AM11/17/10
to Vlad Losev, paolo achdjian, Google C++ Mocking Framework

paolo achdjian

unread,
Nov 18, 2010, 2:54:48 AM11/18/10
to Google C++ Mocking Framework
Hi Vlad,

thanks a lot.

Paolo

On Nov 17, 4:30 pm, Vlad Losev <v...@losev.com> wrote:
> I think I see the problem now. Mockstb_time doesn't have a virtual
> destructor.
>
> ...
>
> read more »
Reply all
Reply to author
Forward
0 new messages