Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL containers memory issue [duplicate]

I'm implementing my own graph library in linux (Fedora 10 and CentOS 5) with gcc 4.3.2 and using STL containers then I found some problems with memory. When I build my graph, I use a lot of memory enough to be view in top or another memory usage tool. I'm sure that I'm deallocating that memory (I reviewed the code again and again and I used valgrind to check for memory leak), but the memory remains in use (I can view this in top or cat /proc/meminfo) and when I create the graph once again, it does not increase memory usage, apparently reusing the allocated memory.

After several days of debugging, I created a very simple code that has the same problem.

#include <iostream>
#include <list>

// Object that occupies 128KB.
// Data is not important.
class MyObject
{
public:
    int * a;
    int * b;
    int * c;
    int * d;

    MyObject( )
    {
        a = new int[ 8192 ];
        b = new int[ 8192 ];
        c = new int[ 8192 ];
        d = new int[ 8192 ];
    }

    MyObject( const MyObject & m )
    {
        a = new int[ 8192 ];
        b = new int[ 8192 ];
        c = new int[ 8192 ];
        d = new int[ 8192 ];
    }

    ~MyObject( )
    {
        delete [] a;
        delete [] b;
        delete [] c;
        delete [] d;
    }

    void operator=( const MyObject &m )
    {
        //Do nothing.
    }
};

typedef std::list< MyObject > list_t;

#define MB_TO_ALLOC 1000    // Size in MB that the program must alloc.

#define SLEEP_TIME 5        // Time in seconds that the program must wait until go to another step. 
                        // It's used to give sufficient time for tools update the memory usage

int main( )
{
    std::cout << "Alloc..." << std::endl;

    list_t * list = new list_t( );

    // Number of objects for alloc MB_TO_ALLOC amount of memory
    int nObjects = MB_TO_ALLOC * 1024 / 128;

    for( int i = 0; i < nObjects; ++i )
        list->push_back( MyObject( ) );

    std::cout << SLEEP_TIME << "s to Dealloc..." << std::endl;

    // Wait some time for a tool (like top) to update the memory usage
    sleep( SLEEP_TIME );

    std::cout << "Dealloc..." << std::endl;

    delete list;

    std::cout << SLEEP_TIME << "s to Alloc..." << std::endl;

    // Wait some time for a tool (like top) to update the memory usage
    sleep( SLEEP_TIME );

    //Repeats the procedure for evaluating the reuse of memory
    std::cout << "Alloc..." << std::endl;

    list = new list_t( );

    for( int i = 0; i < nObjects; ++i )
        list->push_back( MyObject( ) );

    std::cout << SLEEP_TIME << "s to Dealloc..." << std::endl;

    sleep( SLEEP_TIME );

    delete list;
}

I tried to use simple array or my own list class, but in these cases, the memory is deallocated normally.

Does anyone know what's going on? How to prevent this memory to be "reserved"?

Thanks!

-- Bruno Caponi

like image 738
Bruno Caponi Avatar asked Dec 28 '22 06:12

Bruno Caponi


2 Answers

In addition to the STL container, it might be the libc itself doing so (the new/delete - malloc/free implementation). Userspace libraries are at liberty to retain memory for later reuse. Allocating / deallocating is an expensive operation (in terms of clock cycles), so many implementations try to avoid this.

like image 198
DevSolar Avatar answered Jan 05 '23 04:01

DevSolar


gcc STL has its own memory managment layer that grabs big chunks of memory and doesn't give them back ; there is a env variable you can set to make it use raw new calls

GLIBCPP_FORCE_NEW=1

I assume this makes it free it too. This env var is typically used when using valgrind so that valgrind doesnt think things leaked

like image 24
pm100 Avatar answered Jan 05 '23 05:01

pm100