Search code examples
c++stlc++builderc++builder-6fastmm

FastMM reports memory leaks on STL containers in C++ Builder 6


When I create an empty console application and use an STL container in it, FastMM reports a memory leak when the application is closed.

For example, if I create a std::vector<int> in main():

std::vector<int> v;

Compile, run and close, no leaks are reported.

If I do:

std::vector<int> v;
v.push_back(100);

I get:

This application has leaked memory. The small block leaks are:

309 - 340 bytes: Unknown x 1

Similarly, I get a leak reported on:

std::vector<int> v;
v.push_back(100);
v.clear();

And also a leak is reported on:

std::vector<int> v;
v.reserve(1);

For some containers, like std::deque, its enough just to create one, and even without altering its content a leak is reported when the application is closed.

Can anyone explain what is happening? I use Borland C++Builder 6 and FastMM4. I've been changing various settings in FastMMOptions.inc, however I'm still seeing these leaks reported.


Solution

  • Clearing a std::vector does not deallocate the memory used for the vector's internal array, it merely destructs the items inside the array and then sets the std::vector::size() to 0. The array itself is still allocated so it can be reused for new items pushed in the vector. The vector's destructor will deallocate the array.

    In C++Builder 6, the default STL library is STLPort (replaced with Dinkumware in C++Builder 2006). STLPort's implementation of the ~std::vector() merely destructs the array items (as if clear() has been called) but does not deallocate the array itself, thus the "leak" you are seeing. Which is not actually a leak at all, according to the following FAQ on the STLPort website:

    Q6.2 My tool detect memory leaks in application with STLport. Is this leak from STLport?

    A6.2 In most cases this are 'pseudo memory leaks' that some tools wrongly supports.

    In the default compile of STLport, the node allocator is used to allocate internal memory. The node allocator works by pre-allocating a large chunk of memory and handing out small memory blocks out. The memory chunk is not freed during running an application that uses STLport (i.e. it don't returned to system, There are tools like BoundsChecker, Purify or Valgrind that check for memorytml leaks, for memory that isn't freed when no longer used. These tools may report false memory leaks when one uses STLport's node allocator. The memory chunk is normally freed at application end, but the memory checkers usually report memory leaks before that point. Another memory problem might be reported when you use shared libraries (e.g. DLL, this problem specific for Windows DLL model) that uses STLport internally and are statically link to it. If memory is allocated in a dll and released in an other then the STLport node allocator will keep the released memory for a future use. If you do not use this memory then your application global memory consumtion will grow until the appli crash even if there is no realy memory leak. This is why you should always use a coherent configuration everything in dll or everything in static lib.

    There are ways to remove the pseudo memory leaks (since the memory is properly freed at the end of the program, the leaks are just pseudo-ones). You could use another allocator that is used in STLport. Open the file "stlport/stl/_site_config.h" and uncomment either one of the following:

    _STLP_USE_NEWALLOC   enables a simple allocator that uses "new/delete"
    _STLP_USE_MALLOC     enables a simple allocator that uses "malloc/free"
    

    The new/delete allocator has the advantage of giving an entry point to track memory starvation, see set_new_handler in your compiler doc or the C++ Standard for more information.

    Alternatively you can define the following symbol, just uncomment it in "stlport/stl/_site_config.h".

    _STLP_LEAKS_PEDANTIC
    

    The symbol forces freeing all memory chunks. Also see the comments around the symbol in the config file.

    Note that you have to recompile STLport AND your application and all of your dependent libraries if you make any change to the file!

    There are also some defines that help in debugging memory problems in STLport. In _STLP_DEBUG mode, just also define the following symbols, either in "./stlport/stl_user_config.h" or in your project settings:

    _STLP_DEBUG_ALLOC
    _STLP_DEBUG_UNINITIALIZED        
    

    You don't need to rebuild STLport for these options, but you have to rebuild your application and all of your dependent libraries if you make any change to the file.

    That said, the RogueWave STL, which was used in earlier C++Builder versions, is also shipped with C++Builder 6 for backwards compatibility with older code, and does not suffer from this issue. You can switch from STLPort to RogueWave by defining _USE_OLD_RW_STL in your project's conditionals list.