locked
Deallocating CMap memory RRS feed

  • Question

  • Hi,

    I am new to MFC. I am writing a program in which I have to use a CMap to map strings with pointers to CSocket derived objects as follows:

    In one of my dialog class definition:
    CMap<LPCSTR, LPCSTR, CMyConnectionSocket *, CMyConnectionSocket *&> m_mapPConnections;
    

    To insert new values to the map I wrote following code:
    CMyConnectionSocket *pConnectionSocket = new CMyConnectionSocket();
    // After I provide a valid value to pConnectionSocket
    m_mapPConnections.SetAt((LPCSTR)strClientID.GetBuffer(), pConnectionSocket); // Assume strClientID has a valid string value
    

    Then I use the map and when I am done using a socket for a particular strClientID, I remove the map entry:
    m_mapPConnections.RemoveKey((LPCSTR)strClientID.GetBuffer());
    

    The question is: Does the above statement deallocates the memory I allocated to CMyConnectionSocket object? Or it just removes its reference from the map?

    Finally, when my dialog is closed, I want to make sure all map memory is deallocated. But I cannot find a way to ensure this.

    Please help.

    Thanks in advance.

    Vaibhav
    • Edited by vaibhav276 Wednesday, March 17, 2010 4:31 AM Looking ugly due to lack of spaces between lines
    Wednesday, March 17, 2010 4:29 AM

Answers

  • You have to manually call delete on each of the elements in the map.
    After this you can call RemoveKey on each item or RemoveAll to remove all map entries.
    If you do not do delete on each entry, you will get a memory leak.


    «_Superman_»
    Microsoft MVP (Visual C++)
    • Marked as answer by vaibhav276 Thursday, March 18, 2010 3:23 AM
    Wednesday, March 17, 2010 6:46 AM
  • To add to what _Superman_ wrote, you may want to consider STL container classes and smart pointers. In particular, I'm thinking of STL's std::map instead of MFC's CMap, and of shared_ptr smart pointer.
    shared_ptr plays well with STL containers, and you could use a map like this:

    // Map from string to socket smart pointer
    map< CString, shared_ptr< CMyConnectionSocket > > m_mapPConnections;
    

    Note that STL containers like map can store convenient MFC/ATL classes like CString, as well.

    In this way, you don't have to pay attention to the life-time of CMyConnectionSocket pointers in the map; shared_ptr, destructors and C++ RAII pattern will take care of that.

    Giovanni

    • Marked as answer by vaibhav276 Thursday, March 18, 2010 3:23 AM
    Wednesday, March 17, 2010 10:55 AM

All replies

  • You have to manually call delete on each of the elements in the map.
    After this you can call RemoveKey on each item or RemoveAll to remove all map entries.
    If you do not do delete on each entry, you will get a memory leak.


    «_Superman_»
    Microsoft MVP (Visual C++)
    • Marked as answer by vaibhav276 Thursday, March 18, 2010 3:23 AM
    Wednesday, March 17, 2010 6:46 AM
  • To add to what _Superman_ wrote, you may want to consider STL container classes and smart pointers. In particular, I'm thinking of STL's std::map instead of MFC's CMap, and of shared_ptr smart pointer.
    shared_ptr plays well with STL containers, and you could use a map like this:

    // Map from string to socket smart pointer
    map< CString, shared_ptr< CMyConnectionSocket > > m_mapPConnections;
    

    Note that STL containers like map can store convenient MFC/ATL classes like CString, as well.

    In this way, you don't have to pay attention to the life-time of CMyConnectionSocket pointers in the map; shared_ptr, destructors and C++ RAII pattern will take care of that.

    Giovanni

    • Marked as answer by vaibhav276 Thursday, March 18, 2010 3:23 AM
    Wednesday, March 17, 2010 10:55 AM
  • Hi _Superman_, Giovanni:

    Thanks for your replies.

    @_Superman_: Could you also tell me the CMap member which can be used to iterate sequentially through the whole map and retrieve the values?

    @Giovanni: I like your idea of using stl and boost libraries but I am afraid this will increase the size of my executable. Please tell me is this a myth or it is correct? I read somewhere that stl maps are faster than CMap. Is this true?

    Thanks again.

    Vaibhav
    Wednesday, March 17, 2010 1:57 PM
  • @Giovanni: I like your idea of using stl and boost libraries but I am afraid this will increase the size of my executable. Please tell me is this a myth or it is correct? I read somewhere that stl maps are faster than CMap. Is this true?



    I believe that using STL map and shared_ptr won't significantly increase the size of your executable.
    Note that shared_ptr is implemented as part of VS2008 SP1 and VS2010; you don't need Boost if you use these versions of VC++ (you may need Boost if you use VS2005 or 2003).

    I have no idea about the performance of STL maps vs. CMap. If you don't have maps with tons of elements, I think that there won't be much difference in speed.
    In general, my rule of thumb is: first make it work, then make it fast. (And, when in doubt, measure.)

    STL map with shared_ptr smart pointer template can be more convenient than CMap with raw pointers; for example, you don't need to bother about pointers cleanup: with STL containers and shared_ptr you can have both the convenience of the automatic garbage collection and the efficiency of RAII (STL containers with shared_ptr offer kind of a "deterministic garbage collector").

    Giovanni

    Wednesday, March 17, 2010 4:06 PM
  • Hi Giovanni,

    Thanks a lot for your help. 
    Plz give me some time to experiment. I will post if I still falter.

    Thanks
    Vaibhav

    Thursday, March 18, 2010 3:30 AM
  • To iterate through a CMap use the GetStartPosition and GetNextAssoc methods.
    But I agree with Giovanni in that you should be using stl maps instead.

    «_Superman_»
    Microsoft MVP (Visual C++)
    Thursday, March 18, 2010 2:16 PM
  • I read somewhere that stl maps are faster than CMap. Is this true?

    As Giovanni said, there's a good chance that you will not care, or even notice the difference, regardless of your choice. Start with that first!

    That said... There is no good general answer to your question.

    Here's an "abstract" answer...

    First, know the difference between two containers: CMap is a hash map; it uses hashing and related tricks to quickly store/retrieve data. std::map is based on element ordering , not hashing. Implementation-wise, it uses an abstract data structure called rad-black tree (red-black tree is not mandated by the C++ standard, but is used in common implementations).

    Why is it that there's no general answer to your question? There's a vast variety of reasons. For example, any container operation performance depends on it's elements. If they copy faster, container operation will be faster. If you put in pointers to actual elements, copying will be faster still, but then you have to manage heap object lifetime, which has other cost.

    Then, for any hash map (like CMap, or a recent unordered_map of standard C++), speed and "distribution" of hashing function is important. For an ordered map, performance of element ordering (e.g. "operator<") is important. And it all depends on how you use the container.

    Then, there's influence of underlying hardware (not all memory accesses have same "cost", not all CPU logic has same cost...).

    So... Without know a lot of details like the above, nobody can tell you precisely (or even roughly) whether X will be faster than Y. The best you can do is to look for comparative tests on the internet, try to see whether they match your CPU or usage. Or better yet, measure speed on your own code , using competing implementations.

    Goran.
    Thursday, September 2, 2010 7:00 AM