Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory leak with map

I can't clear the map memory (I checked by Valgrind).

#include <map>

class testMap {
    public:
        testMap(){}
        ~testMap();

        void insert_map(int, int);

    private:
          std::map<int,int> _map;
};

void testMap::insert_map(int i, int j){
    _map.insert( pair<int, int>(i,j));
}

I tried _map.clear(), erase(), deleted _map->second manually but not still no luck.


Thanks for all replies. Actually map alone is not a problem but map with a singleton is causing a leak. What's wrong with the code below?

#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include "Object.h"

#include<boost/smart_ptr.hpp>

using namespace std;

class Singleton {
    public:

        // A wrapper around Object class
        class object
        {
            public:
                object() : _object(new Object())
                    {}
                Object get(void)
                    { return _object.get(); }
            private:
                boost::shared_ptr<Object> _object;
        };

        object insert_new(const std::string key)
        {
            _object_maps.insert( pair<string,object>( key, object() ));
            return _object_maps.find( key )->second;
            //_test_object = object();
            //return _test_object;  // Leak goes away if I don't use map.
        }

        static Singleton* Instance();
        void Print();

    protected:
        Singleton(){}
        ~Singleton();

    private:
        static Singleton* _instance;

        std::map<std::string, object > _object_maps;
        object _test_object;
};

Singleton* Singleton::_instance = 0;

Singleton* Singleton::Instance() {
    if( _instance ==0 )
    {
        _instance = new Singleton();
    }
    return _instance;
}

void Singleton::Print() {
    std::cout << " Hi I am a singleton object" << std::endl;
}

Singleton::~Singleton()
{
    _object_maps.clear();
}

From another code I was calling by

    Singleton::object _test_object(Singleton::Instance()->insert_new("TEST"));

Is there a problem? I am getting a Valgrind error, like

      ==19584== 17 bytes in 1 blocks are possibly lost in loss record 31,429 of 52,291
      ==19584==    at 0x69A1642: operator new(unsigned int) (vg_replace_malloc.c:255)
      ==19584==    by 0x772CB0A: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.8)
      ==19584==    by 0x772D904: ??? (in /usr/lib/libstdc++.so.6.0.8)
       ==19584==    by 0x772DB16: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.8)
       ==19584==    by 0xBF1BC17: test::test() (test.C:34)
       ==19584==    by 0xBF1DB66: G__testDict_143_0_1(G__value*, char const*, G__param*, int) (testDict.C:190)
       ==19584==    by 0x70EA4E5: Cint::G__ExceptionWrapper(int (*)(G__value*, char const*, G__param*, int), G__value*, char*, G__param*, int) (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x71EF2E4: G__call_cppfunc (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x71C0095: G__interpret_func (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x71AF883: G__getfunction (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x71D8CC1: G__new_operator (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x718D07F: G__getexpr (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x717724E: G__define_var (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x71FDEC6: G__defined_type (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x7201A6D: G__exec_statement (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x71BF6C8: G__interpret_func (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x71AF62F: G__getfunction (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x718437D: G__getitem (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x7189F12: G__getexpr (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
       ==19584==    by 0x719713F: G__calc_internal (in /afs/rhic.bnl.gov/@sys/opt/phenix/root-5.17.01/lib/libCint.so)
like image 769
Abhisek Sen Avatar asked Jul 21 '11 01:07

Abhisek Sen


People also ask

How do you detect a memory leak?

The best approach to checking for the existence of a memory leak in your application is by looking at your RAM usage and investigating the total amount of memory been used versus the total amount available. Evidently, it is advisable to obtain snapshots of your memory's heap dump while in a production environment.

What is memory leak with an example?

Memory leaks are a common error in programming, especially when using languages that have no built in automatic garbage collection, such as C and C++. Typically, a memory leak occurs because dynamically allocated memory has become unreachable.

What is the main cause of memory leaks?

A memory leak starts when a program requests a chunk of memory from the operating system for itself and its data. As a program operates, it sometimes needs more memory and makes an additional request.

Is memory leak serious?

Very dangerous. Memory leaks in the kernel level lead to serious system stability issues. Kernel memory is very limited compared to user land memory and should be handled cautiously.


2 Answers

Short answer:
you explicitly declared but not defined the destructor (forgot {}).

Long answer:

  1. Your code does not even compile. Missing {} in class destructor and std:: in front of pair.
  2. Corrected and completed with main:

    #include <map>
    
    class testMap {
      public:
        testMap() {}
        ~testMap() {};
    
        void insert_map(int, int);
    
      private:
        std::map<int,int> _map;
    };
    
    void testMap::insert_map(int i, int j) {
        _map.insert(std::pair<int, int>(i,j));
    }
    
    int main() {
        testMap t;
        t.insert_map(12, 34);
        return 0;
    }
    
  3. Compiled on 32-bit Ubuntu 11.04:

    g++ leak.cpp -o leak
    
  4. Run under valgrind supervision:

    valgrind ./leak
    ==20773== Memcheck, a memory error detector
    ==20773== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
    ==20773== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
    ==20773== Command: ./leak
    ==20773== 
    ==20773== 
    ==20773== HEAP SUMMARY:
    ==20773==     in use at exit: 0 bytes in 0 blocks
    ==20773==   total heap usage: 1 allocs, 1 frees, 24 bytes allocated
    ==20773== 
    ==20773== All heap blocks were freed -- no leaks are possible
    ==20773== 
    ==20773== For counts of detected and suppressed errors, rerun with: -v
    ==20773== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 6)
    
  5. No memory leakage.

Probably your compiler auto-defines a completely empty class destructor (because of missing {}), not auto-calling anymore on exit the private member map destructor.

Hope it helps :)

like image 59
Vanni Totaro Avatar answered Sep 20 '22 15:09

Vanni Totaro


Try:

{
    std::map<int,int> empty_map;
    empty_map.swap(_map);
}

(At least, this is the usual way to convince a standard library container actually to release its memory.)

like image 39
Nemo Avatar answered Sep 23 '22 15:09

Nemo