Unit test to verify no memory gets allocated

1,603 views
Skip to first unread message

Patrick Doyle

unread,
Apr 13, 2012, 8:07:05 PM4/13/12
to Google C++ Testing Framework
Can anyone give me tips (or even example) of how to write a unit test
that verifies that a creating a local variable instance of a class and
invoking member functions on that class does not result in any memory
being allocated?

I designing a class for use in a time critical application that cannot
allocate any memory. Since it's important that this class not
allocate any memory, I would like to test for that.

Thanks for the help.

--wpd

Kenneth Suralta

unread,
Apr 13, 2012, 8:48:02 PM4/13/12
to Patrick Doyle, Google C++ Testing Framework
Hi,

I see 2 ways of doing this.
First is to compare heap size before and after invoking the function.
Determining the heap size varies on different OS.
Second is to override either malloc, new or both and set some flag to
indicate memory has been allocated.

Best Regards,
Kenneth

Patrick Doyle

unread,
Apr 13, 2012, 9:41:34 PM4/13/12
to Google C++ Testing Framework
Arrghh... Sorry for the double post Kenneth, I mean to "Reply-All".

On Fri, Apr 13, 2012 at 8:48 PM, Kenneth Suralta <ksur...@gmail.com> wrote:
> Hi,
>
> I see 2 ways of doing this.
> First is to compare heap size before and after invoking the function.
> Determining the heap size varies on different OS.
> Second is to override either malloc, new or both and set some flag to
> indicate memory has been allocated.

Both are great ideas...

The problem with the first idea, as you mention, is how to determine
the heap size portably?  Also, how would I detect if memory were
allocated and then returned?

I like the idea of overriding malloc, but, am I guaranteed by the C++
standard that all calls to new (except for "placement new" calls)
result in a call to malloc?  Also, presumably the test framework
and/or other tests I might be running will need to call malloc()
either directly or indirectly (via new).  How do I (portably) pass
through the memory allocation calls for those other tests?

Thanks for the tips.  Please keep them coming.

--wpd

Mika Raento

unread,
Apr 14, 2012, 10:34:08 AM4/14/12
to Patrick Doyle, Google C++ Testing Framework
Checking for memory leaks is definitely platform-dependent and may not be feasible on all platforms (think of a platform that lazily allocates cached data with no release API, like the iPhone; or a platform that allocates thread-local data and crashes if it's freed and then the library called into again, like Symbian).

Even if you have a platform that supports memory checking (Linux+tcmalloc; Microsoft's debug heap) it may not be feasible to do it at the granularity of a single unit test.

That said, with the right platform and knowledge it _is_ possible. See http://mikie.iki.fi/wordpress/?p=69 and it's comments for some examples; but I don't think anybody's able to help you beyond that without specifying the platform (OS, compiler, allocator).

BR,
    Mika

Patrick Doyle

unread,
Apr 14, 2012, 12:42:57 PM4/14/12
to Mika Raento, Google C++ Testing Framework
On Sat, Apr 14, 2012 at 10:34 AM, Mika Raento <mi...@iki.fi> wrote:
> Checking for memory leaks is definitely platform-dependent and may not be
> feasible on all platforms (think of a platform that lazily allocates cached
> data with no release API, like the iPhone; or a platform that allocates
> thread-local data and crashes if it's freed and then the library called into
> again, like Symbian).
>
> Even if you have a platform that supports memory checking (Linux+tcmalloc;
> Microsoft's debug heap) it may not be feasible to do it at the granularity
> of a single unit test.
>
> That said, with the right platform and knowledge it _is_ possible.
> See http://mikie.iki.fi/wordpress/?p=69 and it's comments for some examples;
> but I don't think anybody's able to help you beyond that without specifying
> the platform (OS, compiler, allocator).

Hi Mika,
Thanks for the link... I'll go read about User::Heap() and see if it applies...

My first impression is to wonder if User::Heap() might be Symbian
specific, but my good buddy Google will help me figure that out.

In the mean time, I'm running my unit tests on my development host,
either a Linux box or a MacBook, depending on which machine I'm
sitting in front of at any given time. Its the "granularity of a
single unit test" (or test fixture) part that I was hoping to learn
if/how others had dealt with.

Basically, I want to test for and ensure that no memory gets
dynamically allocated during the lifetime of a specific object. I
could override "new" for that object, but that doesn't help -- I want
to test for and ensure that none of the member functions allocate
memory either.

I'm sensing that the "Too hard" LED is starting to blink, and I'll
probably let this go. But I wanted to ask more experienced members of
the community before I did that.

Again, thanks for the response, and for the link. I'll go see where
that takes me now.
--wpd

Patrick Doyle

unread,
Apr 16, 2012, 8:53:11 PM4/16/12
to Yury Mikhaylov, Google C++ Testing Framework
On Mon, Apr 16, 2012 at 8:41 PM, Yury Mikhaylov
<yury.mi...@gmail.com> wrote:
> Hello Patrick,
>
> Would it be feasible to include your class _implementation_ directly into
> the test? It is not an elegant trick by any means, but it did helped me test
> some embedded C code. I'd use something like this:
>
> class MockHelper
> {
> public:
>     MOCK_METHOD2(malloc, void * (size_t));
> } g_mocks;
>
> #define malloc g_mocks->malloc
> #include "../src/target_class.cpp"
> #undef malloc
>
> TEST(Suite, Test1)
> {
>     EXPECT_CALL(g_mocks, malloc(15));
>
>     target_class().perform_magic();
> }
>
> TEST(Suite, Test2)
> {
>     EXPECT_CALL(g_mocks, malloc(_))
>         .Times(0);
>
>     target_class().perform_magic();
> }
>
> Ugly as hell, but 100% portable :-)

Hmmm.... That's clever.

But I'm not sure it will catch the sort of thing I was hoping to
catch. (Nor am I sure, at this point that it is possible to catch the
thing I was hoping to catch).

Your suggestion will catch any explicit calls to malloc(), but not (I
don't think) implicit calls via new. Nor will it catch calls to
malloc (explicit or implicit) from functions called by the member
functions of my class.

I was hoping there was some clever trick to catch this, but I think
I'm going to have to rely on the good old fashioned method of coding
carefully :-)

--wpd

Yury Mikhaylov

unread,
Apr 16, 2012, 8:41:29 PM4/16/12
to Patrick Doyle, Google C++ Testing Framework
Hello Patrick,

Would it be feasible to include your class _implementation_ directly into the test? It is not an elegant trick by any means, but it did helped me test some embedded C code. I'd use something like this:

class MockHelper
{
public:
    MOCK_METHOD2(malloc, void * (size_t));
} g_mocks;

#define malloc g_mocks->malloc
#include "../src/target_class.cpp"
#undef malloc

TEST(Suite, Test1)
{
    EXPECT_CALL(g_mocks, malloc(15));

    target_class().perform_magic();
}

TEST(Suite, Test2)
{
    EXPECT_CALL(g_mocks, malloc(_))
        .Times(0);

    target_class().perform_magic();
}

Ugly as hell, but 100% portable :-)

- Yury
Reply all
Reply to author
Forward
0 new messages