STL map and memory management (clear() )

Discussion in 'C++' started by Jan, Dec 15, 2005.

  1. Jan

    Jan Guest

    Hi there,
    i've got an STL map with something like this ( map<string, Object*>
    xyz; )
    What happens when I call xyz.clear()?
    Is only the map cleared or the map and the Objects, so that the memory
    is free again?
    Have I to delete every single Object?

    Thanks for replying,
    Jan
     
    Jan, Dec 15, 2005
    #1
    1. Advertising

  2. Jan

    Mark P Guest

    Jan wrote:
    > Hi there,
    > i've got an STL map with something like this ( map<string, Object*>
    > xyz; )
    > What happens when I call xyz.clear()?
    > Is only the map cleared or the map and the Objects, so that the memory
    > is free again?
    > Have I to delete every single Object?
    >
    > Thanks for replying,
    > Jan
    >

    clear() empties out the contents of the map. It doesn't do anything
    with the Object*; in particular it doesn't delete them.
     
    Mark P, Dec 15, 2005
    #2
    1. Advertising

  3. Jan

    Jan Guest

    thanks :)
     
    Jan, Dec 15, 2005
    #3
  4. Jan

    Axter Guest

    Jan wrote:
    > Hi there,
    > i've got an STL map with something like this ( map<string, Object*>
    > xyz; )
    > What happens when I call xyz.clear()?
    > Is only the map cleared or the map and the Objects, so that the memory
    > is free again?
    > Have I to delete every single Object?
    >
    > Thanks for replying,
    > Jan


    None of the STL containers will delete a pointer type.
    I recommend you use smart pointers instead of raw pointers with STL
    containers.
    You can not use auto_ptr with STL containers, but you can use other
    common smart pointers like boost::shared_ptr and clone pointers like
    copy_ptr and cow_ptr.

    http://www.boost.org/libs/smart_ptr/shared_ptr.htm

    http://code.axter.com/copy_ptr.h

    http://code.axter.com/cow_ptr.h
     
    Axter, Dec 15, 2005
    #4
  5. Mark P wrote:
    >
    > It doesn't do anything with the Object*; in particular it doesn't delete them.
    >


    Wrong!
    Object* is a pointer or more descriptively - it is a pointer type to
    objects of type of Object.
    Every STL container destroys its elements while being destroyed itself.
    So, when you call std::map::clear() then all contained pointers will be
    destroyed, BUT NOT objects pointed by them. All those objects will stay
    alive in memory.
    In your case, container-of-pointers, no STL container will delete
    instances of Object class for you because it stores pointers, not
    objects. So, you have to destroy those instances by yourself: iterated
    through std::map elements and call delete on contained pointer.

    Cheers
    --
    Mateusz Loskot
    http://mateusz.loskot.net
     
    Mateusz Loskot, Dec 15, 2005
    #5
  6. I'd like to complement my last post.
    Currently, I'm reading amazing book "C++ Gotchas: Avoiding Common
    Problems in Coding and Design" by Stephen C. Dewhurst.
    There is "Gotcha #83: Failure to Distinguish Aggregation and
    Acquaintance" chapter which, what at first sight may seem, does not
    drift a-way from the subject.

    It is really woth to read, especially when you are working with
    containers-of-pointers.

    At the end, author express' very neatly - in one sentence - what I
    wanted to say to my previous post:

    "For pointer elements, the standard* containers will clean up the
    pointers but not the objects to which they refer."

    * - means STL containers
    Cheers
    --
    Mateusz Loskot
    http://mateusz.loskot.net
     
    Mateusz Loskot, Dec 16, 2005
    #6
  7. Jan

    Stephen Howe Guest

    > Wrong!
    > Object* is a pointer or more descriptively - it is a pointer type to
    > objects of type of Object.
    > Every STL container destroys its elements while being destroyed itself.
    > So, when you call std::map::clear() then all contained pointers will be
    > destroyed...


    How is Mark P wrong?
    A pointer has no destructor, so clear() has nothing to do for each value
    element.

    Stephen Howe
     
    Stephen Howe, Dec 16, 2005
    #7
  8. I said this sentence is wrong: "It doesn't do anything with the
    Object*".
    OK maybe not wrong, but not precise.

    Your sentence "has nothing to do" is also not precise.
    Why? Pointers are "cleaned up"*** after std::map::clear() is called.

    *** - See my previous post where I quoted Stephen C. Dewhurst

    If there "nothing is done" there also pointers would not be cleared,
    pointers are data, they occupy space in memory, just as integers or
    objects. So, they must be cleaned (we can say "destroyed" and it won't
    be mistake).

    Cheers
    --
    Mateusz Loskot
    http://mateusz.loskot.net
     
    Mateusz Loskot, Dec 16, 2005
    #8
  9. Jan

    Guest

    Jan wrote:
    > Hi there,
    > i've got an STL map with something like this ( map<string, Object*>
    > xyz; )
    > What happens when I call xyz.clear()?
    > Is only the map cleared or the map and the Objects, so that the memory
    > is free again?
    > Have I to delete every single Object?


    Depends. If the Object* are non-owning (e.g. because xyx is just a way
    of associating names with list<Object> entries), no. The list<Object>
    will get them. However, if the Object* are owning, then yes of course.

    Besides, how would the STL know whether to call delete or delete[]
    or &Object::Delete ? And what if it wasn't Object* but char*?

    HTH,
    Michiel Salters
     
    , Dec 16, 2005
    #9
  10. Jan

    Stephen Howe Guest

    > Your sentence "has nothing to do" is also not precise.
    > Why? Pointers are "cleaned up"*** after std::map::clear() is called.
    >
    > If there "nothing is done" there also pointers would not be cleared,
    > pointers are data, they occupy space in memory, just as integers or
    > objects. So, they must be cleaned (we can say "destroyed" and it won't
    > be mistake).


    Your not being precise.
    What do you mean by pointers must be cleaned?
    What does "cleaning" involve?

    Stephen Howe
     
    Stephen Howe, Dec 17, 2005
    #10
  11. I mean that "place" in memory where pointer (address) is stored is
    cleaned up/cleared/erased.

    Cheers
    --
    Mateusz Loskot
    http://mateusz.loskot.net
     
    Mateusz Loskot, Dec 17, 2005
    #11
  12. Jan

    Jim Langston Guest

    "Mateusz Loskot" <> wrote in message
    news:...
    >I said this sentence is wrong: "It doesn't do anything with the
    > Object*".
    > OK maybe not wrong, but not precise.
    >
    > Your sentence "has nothing to do" is also not precise.
    > Why? Pointers are "cleaned up"*** after std::map::clear() is called.
    >
    > *** - See my previous post where I quoted Stephen C. Dewhurst
    >
    > If there "nothing is done" there also pointers would not be cleared,
    > pointers are data, they occupy space in memory, just as integers or
    > objects. So, they must be cleaned (we can say "destroyed" and it won't
    > be mistake).


    His statement was now wrong, you just didn't like how it was phrased :D I
    understood what he was saying.
     
    Jim Langston, Dec 18, 2005
    #12
  13. Jim Langston napisał(a):
    > "Mateusz Loskot" <> wrote in message
    >>
    >>*** - See my previous post where I quoted Stephen C. Dewhurst
    >>
    >>If there "nothing is done" there also pointers would not be cleared,
    >>pointers are data, they occupy space in memory, just as integers or
    >>objects. So, they must be cleaned (we can say "destroyed" and it won't
    >>be mistake).

    >
    >
    > His statement was now wrong
    > [...]
    >


    Why?

    Cheers

    --
    Mateusz Åoskot
    http://mateusz.loskot.net
     
    =?UTF-8?B?TWF0ZXVzeiDFgW9za290?=, Dec 19, 2005
    #13
  14. Jan

    Stephen Howe Guest

    >I mean that "place" in memory where pointer (address) is stored is
    > cleaned up/cleared/erased.


    Now you are not being precise.

    What do mean that the "pointer is cleaned up/cleared/erased?"
    What _exactly_ happens?
    Do you mean, for instance, that the pointer is set to NULL?

    Please enlighten me. Thanks.

    Stephen Howe
     
    Stephen Howe, Dec 20, 2005
    #14
  15. Stephen Howe wrote:
    >>I mean that "place" in memory where pointer (address) is stored is
    >>cleaned up/cleared/erased.

    >
    >
    > Now you are not being precise.
    >
    > What do mean that the "pointer is cleaned up/cleared/erased?"
    > What _exactly_ happens?
    > Do you mean, for instance, that the pointer is set to NULL?
    >
    > Please enlighten me. Thanks.


    Hm, seems you've catched me.
    I know how to _use_ it but I don't know exactly how it's implemented.
    Setting it to NULL seems to not to be enough. Memory should albo be
    deallocated.

    I'd be glad to hear a deep explanation of this problem from soe Gurus.
    Is there anyone who could explain those internals?

    Cheers

    --
    Mateusz Åoskot
    http://mateusz.loskot.net
     
    =?UTF-8?B?TWF0ZXVzeiDFgW9za290?=, Dec 20, 2005
    #15
  16. Jan

    Mark P Guest

    Mateusz Åoskot wrote:
    > Stephen Howe wrote:
    >
    >>> I mean that "place" in memory where pointer (address) is stored is
    >>> cleaned up/cleared/erased.

    >>
    >>
    >>
    >> Now you are not being precise.
    >>
    >> What do mean that the "pointer is cleaned up/cleared/erased?"
    >> What _exactly_ happens?
    >> Do you mean, for instance, that the pointer is set to NULL?
    >>
    >> Please enlighten me. Thanks.

    >
    >
    > Hm, seems you've catched me.
    > I know how to _use_ it but I don't know exactly how it's implemented.
    > Setting it to NULL seems to not to be enough. Memory should albo be
    > deallocated.
    >
    > I'd be glad to hear a deep explanation of this problem from soe Gurus.
    > Is there anyone who could explain those internals?
    >
    > Cheers
    >


    That's exactly the point-- you're fussing about implementation details
    which aren't specified by (nor relevant to) the operation of the class.
    (I'll concede that my original reply was not precise enough for legal
    work, but I think the message was clear to everyone, particularly the
    original poster.)

    In my limited experience, maps are usually implemented in terms of red
    black trees and the individual data stored in the map are wrapped up in
    some sort of node structure which includes the key, the value, and some
    additional information (for example, pointers to other nodes in the tree).

    You'll get a sense for this if you write your own STL allocator because
    you can then observe the individual memory allocations and
    deallocations. If you have a map<int,int> for example, and sizeof(int)
    = 4, it would be fairly typical to find that each insertion results in
    an allocation of size, say, 24, which you can see is 2 ints plus "some
    other stuff". This confirms the sometimes surprising fact that a map
    passed an allocator<T> when constructed may very likely never allocate
    space for a T. Instead the allocator rebind mechanism is used to
    allocate space for some other object-- in this case a tree node.

    In fact, to really throw a wrench into things (and return to your point
    above), I've seen implementations (e.g. RogueWave) which use block
    allocations so that as soon as one item is added to the map, space is
    allocated for say 32 items. Conversely, it's possible to erase items
    from such a map and have no memory immediately deallocated. To the
    user the map must appear not to contain the erased items, but there may
    be no memory deallocation until a whole block's worth of items have been
    erased. Or for that matter, until the implementation feels like
    deallocating the memory.

    Mark
     
    Mark P, Dec 20, 2005
    #16
  17. Mark P wrote:
    > Mateusz Åoskot wrote:
    >> Stephen Howe wrote:
    >>
    >>> What do mean that the "pointer is cleaned up/cleared/erased?"
    >>> What _exactly_ happens?
    >>> Do you mean, for instance, that the pointer is set to NULL?
    >>>
    >>> Please enlighten me. Thanks.

    >>
    >> Hm, seems you've catched me.
    >> I know how to _use_ it but I don't know exactly how it's implemented.
    >> Setting it to NULL seems to not to be enough. Memory should albo be
    >> deallocated.
    >>
    >> I'd be glad to hear a deep explanation of this problem from soe Gurus.
    >> Is there anyone who could explain those internals?

    >
    > That's exactly the point-- you're fussing about implementation details
    > which aren't specified by (nor relevant to) the operation of the class.


    Yes, definitely you are right.
    You know, I always imagine "cleaning of pointers" similarly to cleaning
    (freeing) memory occupied as by int, double.
    Just as it is here presented by scopes:

    {
    int i = 0;
    }

    // here i is not known and seems to be freed

    I imagine it similarly with points:

    {
    int* pi = 0;
    }

    // here 4 bytes occupied by pi (pointer) are cleaned (free)

    Certainly, I'm completely not sure about if it's implementated that way.

    >
    > [...]
    >


    Thanks for interesting explanation.

    Cheers
    --
    Mateusz Åoskot
    http://mateusz.loskot.net
     
    =?UTF-8?B?TWF0ZXVzeiDFgW9za290?=, Dec 22, 2005
    #17
  18. Jan

    Guest

    Mateusz Loskot wrote:
    > You know, I always imagine "cleaning of pointers" similarly to cleaning
    > (freeing) memory occupied as by int, double.
    > Just as it is here presented by scopes:
    >
    > {
    > int i = 0;
    > }
    >
    > // here i is not known and seems to be freed


    Could be. It's just not name-able. If it was a "static int" it won't be
    freed
    but it won't be name-able outside the scope either. The fact that i is
    invisible outside the scope allows optimizers to do fancy things, so
    you
    cant say exactly what happens.

    > I imagine it similarly with points:
    >
    > {
    > int* pi = 0;
    > }
    >
    > // here 4 bytes occupied by pi (pointer) are cleaned (free)


    With pointers you have to distiguish between the pointer itself (pi)
    and
    the pointed-to (*pi). In your case, pi is a null pointer so there is no

    pointed-to (yet). At the }, the memory used to hold the null pointer
    (sizeof(int*) bytes) is reusable. The reuse will typically be by
    another
    line like double dd = 5.0; . Therefore, the compiler won't clean up
    the bytes at the } but simply overwrites the old value if/when a new
    variable is defined. That saves time.

    if you had
    void foo( int* pi ) {
    pi = 0;
    }
    it would be assignment. pi is a copy of a pointer. The original pointer
    can be found
    in the caller of foo(). The assignment to pi sets it to the null
    pointer. The original
    pointer remains unchanged. So, if it pointed to an int, it will
    continue to do so.
    Now, I think it's obvious why going out of scope doesn't free the
    pointed-to memory.

    PS. an int often, but not always is 4 bytes. So is an int* - but not
    every CPU
    is 32/32 bits. C++ doesn't care, 0 is always precisely enough bits.
     
    , Dec 22, 2005
    #18
  19. wrote:
    > Mateusz Loskot wrote:
    >>You know, I always imagine "cleaning of pointers" similarly to cleaning
    >>(freeing) memory occupied as by int, double.
    >>Just as it is here presented by scopes:
    >>
    >>{
    >> int i = 0;
    >>}
    >>
    >>// here i is not known and seems to be freed

    >
    >
    > Could be. It's just not name-able. If it was a "static int" it won't be
    > freed
    > but it won't be name-able outside the scope either. The fact that i is
    > invisible outside the scope allows optimizers to do fancy things, so
    > you cant say exactly what happens.
    >


    I understand it now much better.

    >>I imagine it similarly with points:
    >>
    >>{
    >> int* pi = 0;
    >>}
    >>
    >>// here 4 bytes occupied by pi (pointer) are cleaned (free)

    >
    >
    > With pointers you have to distiguish between the pointer itself (pi)
    > and the pointed-to (*pi).


    I'm sure I understand the difference.

    > In your case, pi is a null pointer so there is no
    > pointed-to (yet).


    Yes, but during this discussion I'm talking about pointer itself but not
    objects pointed by pointer.

    > At the }, the memory used to hold the null pointer
    > (sizeof(int*) bytes) is reusable. The reuse will typically be by
    > another line like double dd = 5.0; .


    Yes, and that seems to be also what I tried to say writting "cleaning
    pointer".

    > Therefore, the compiler won't clean up
    > the bytes at the } but simply overwrites the old value if/when a new
    > variable is defined.
    > That saves time.
    > [...]


    And that explains everything. I wasn't sure exactly what compiler is
    supposed to do with memory occupied by pointer itself.

    >
    > PS. an int often, but not always is 4 bytes. So is an int* - but not
    > every CPU
    > is 32/32 bits. C++ doesn't care, 0 is always precisely enough bits.
    >


    Yes.

    Thanks for clear explanation.
    Cheers
    --
    Mateusz Åoskot
    http://mateusz.loskot.net
     
    =?UTF-8?B?TWF0ZXVzeiDFgW9za290?=, Dec 22, 2005
    #19
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. exits funnel
    Replies:
    3
    Views:
    2,861
    exits funnel
    Jan 30, 2004
  2. Replies:
    2
    Views:
    574
    klaus hoffmann
    Feb 22, 2006
  3. Steve
    Replies:
    2
    Views:
    538
    Andre Kostur
    Nov 6, 2007
  4. kl
    Replies:
    7
    Views:
    1,346
    James Kanze
    Jan 1, 2008
  5. Luca Risolia

    STL map to STL vector

    Luca Risolia, Jan 13, 2014, in forum: C++
    Replies:
    32
    Views:
    433
    Seungbeom Kim
    Jan 18, 2014
Loading...

Share This Page