8

in xxxx.h file:

struct dn_instance_pair
{
    std::string theDn;
    int theInstance;
};
typedef struct dn_instance_pair t_dn_inst_pair;

struct table_rowid_type
{
    char theTable[101];
    sqlite3_int64 theRowid;
    int operation;
};

// static class members
static vector<t_dn_inst_pair> dninstList;
static vector<t_table_rowid_type> tablerowidList;

in xxxx.cpp

// declaration of vectors.
// Included to this post only for completeness.
vector<t_dn_inst_pair> xxxx::dninstList;
vector<t_table_rowid_type> xxxx::tablerowidList;

These vectors are handled in static callback functions, so they must be static too.

In cpputest, when trying to add something in either one of these vectors, a failure happens:

Leak size: 8 Allocated at: <unknown> and line: 0. Type: "new" Content: "<\ufffdP@"

The stuff added to a vector are automatic variables and it happens in a normal function:

t_dn_inst_pair thePair;
thePair.theDn = updated_dn;
thePair.theInstance = updated_instance;

The vector is cleared in the end of the test case:

xxxx::yyyy()->dninstList.clear();

(yyyy() returns a pointer to a singleton xxxx object)

Page http://blog.objectmentor.com/articles/2010/02/04/cpputest-recent-experiences discusses the same kind of memory leak:

"This is a false positive. This is a one-time allocation and a side-effect of C++ memory allocation and static initialization."

So my question is: Is this failure genuinely a false positive ?

br Esko

Esko Hujanen
  • 83
  • 1
  • 3

1 Answers1

6

Have you checked with valgrind? It will distinguish leaked memory that is "definitely lost" from memory that is "still reachable". If it's a false positive it should be still reachable (via pointers in the vector.)

Remember that vector::clear() just destroys the elements, it doesn't deallocate any memory, so capacity() will remain the same.

You could do the swap trick to force the vector to deallocate its memory:

vector<t_dn_inst_pair>().swap(xxxx::yyyy()->dninstList);

That creates a temporary (empty) vector and swaps it with your vector, so your vector's elements and allocated memory will be transferred to the temporary and then destroyed at the end of the statement.

P.S. Singletons suck, don't use them, but why do you access the vector as yyyy()->dninstList (i.e. using operator->) if it's a static member? You could either say xxxx::dninstList or make it a non-static member and access it via the singleton object (but don't forget that singletons suck.)

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Hi Jonathan, Thank you for your answer. Yes, I checked with Valgrind; no memory leaks. valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./executable. I will add the swap trick for deallocating. And will try to change the vectors to non-static and access them via singleton (although it sucks ;). br Esko – Esko Hujanen May 30 '12 at 10:28
  • 3
    I believe it actually appears because of order of destruction. I.e. that the memory actually gets freed, just only after CppUTest already reported the leaks. The reason is that static objects are only destroyed (and free their memory) during global destruction after `main()` function returns, but CppUTest probably reports the leaks at the end of the test driver, which means still in `main()`. That would explain why Valgrind does not show them even with --show-reachable=yes. – Jan Hudec May 30 '12 at 11:12
  • Hi Jonathan, the non-static worked like a charm. I did also the swap. Thanks ! Also thanks to Jan for explanation – Esko Hujanen May 31 '12 at 06:37
  • This works also with `unique_ptr`, the swap solution solved my problem there too! Thanks! – ollo Sep 03 '15 at 19:06