Sign in to follow this  
Syranide

STD/template/memory question (C++)

Recommended Posts

Syranide    375
I'm finding it very hard to find good information on "std" in C++... (I haven't used it myself up until recently) This isn't really STD-related, but considering they should be doing something too then. However, my question is simple, just take the basic hash_map as an example... you send in a key and value (possibly as a pair) ... and yes, no problem, using templating you can also send in whatever type you want. But... what about memory? Say just for instance we send a CString or LPSTR as a key... then, how is it garbage-collected? Because just removing the pair from the hashmap would leave garbage... freeing the pair would cause unwanted behaviour. So, just generally speaking, how does one tackle this? (That is, having a generic class be a container for data and not making it leave garbage or giving the caller a headache)

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by Syranide
However, my question is simple, just take the basic hash_map as an example... you send in a key and value (possibly as a pair) ... and yes, no problem, using templating you can also send in whatever type you want.


Of note is that hash_map is not part of the Standard C++ Library, it is an SGI extension.

Quote:
But... what about memory? Say just for instance we send a CString or LPSTR as a key... then, how is it garbage-collected? Because just removing the pair from the hashmap would leave garbage... freeing the pair would cause unwanted behaviour.


Those objects will be destroyed when the map is, or the member function erase is called with an iterator referencing those given elements.

Quote:
So, just generally speaking, how does one tackle this? (That is, having a generic class be a container for data and not making it leave garbage or giving the caller a headache)


I'm a bit confused what you're trying to ask, exactly. Are you wanting/trying to implement your own container (or container clone)? Also, are you using Managed C++? This is a fairly different beast from Unmanaged C++ although they are obviously related... however, unmanaged C++ does not do garbage-collection in the traditional sense of the phrase - everything is explicit.

I have the feeling that understanding what you're trying to do (like, the actual example) will be the easiest way of understanding what you're trying to ask...

Share this post


Link to post
Share on other sites
Syranide    375
Hmm, ok, might've been a little unclear, was uncertain on how to phrase myself.

I'm using unmanaged C++, and yes I figure that would provide to be a great deal of problem... but apparently, it has been solved someway, or is at least utilized in a satisfying way as std::hash_map etc is used by many.

std::hash_map , isn't that standard? (MSVC .NET 2003)

either way, it is available... however, I can't find any satisfying information on it that even says how it works with garbage collection or if it does it at all or how one should work with it (except for the useless example in MSDN)

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by Syranide
Hmm, ok, might've been a little unclear, was uncertain on how to phrase myself.

I'm using unmanaged C++, and yes I figure that would provide to be a great deal of problem... but apparently, it has been solved someway, or is at least utilized in a satisfying way as std::hash_map etc is used by many.

Correct... prehaps if you explained the problem you were expecting to have?
Quote:
std::hash_map , isn't that standard? (MSVC .NET 2003)

Nope, SGI extension. According to this MSDN documentation hash_map was moved from the std namespace into the stdext namespace "In Visual C++ .NET 2003".
Quote:
either way, it is available...

Not on my system with the std:: prefix. Just alerting you to this fact. There's a possibility it may be added to the standard specification at a later date, but it has not happened yet. As far as I know it's not part of TR1 either.

Quote:
however, I can't find any satisfying information on it that even says how it works with garbage collection or if it does it at all or how one should work with it (except for the useless example in MSDN)


Again, I reiterate: What are you trying to do? Is it...

1) Create a clone or lookalike or parallel to hash_map?
2) Understand how hash_map works so you can best use hash_map?
3) 42

?

Share this post


Link to post
Share on other sites
Syranide    375
Quote:
Original post by MaulingMonkey
1) Create a clone or lookalike or parallel to hash_map?
2) Understand how hash_map works so you can best use hash_map?
3) 42


Still a little unclear about what I mean, I guess...

The problem I'm having is... how does std::hash_map work? I can't find any satisfying documentation on how hash_map actually works... MSDN says nothing except for how do insert a few numbers... no cleaning up classes and so on and searching google doesn't present me with any related information (and one has to keep in mind the so present factor of people teaching wrong).

What am I trying to do? A texture manager, and considering that I want to have IDs widely used I figured having an ID manager would serve my purpose (re-inventing the wheel you might say, and yes I know that, and that is what I want to do right now, and please don't present me with solutions on how to do a texture manager without "solving" this).

So... it boils down to, how does one deal with this, having seen no generic solutions for it, it is hard to find answers as all I've seen are texture managers with internal garbage collection and so on, nothing generic.

Share this post


Link to post
Share on other sites
risingdragon3    382
I'm going to guess what Synranide is trying to say.

He has something like this:

std::hash_map<string, TextureClass*> textures;

and wants to know about what happens to the memory when you do

textures.clear();

for example. The answer to the question is that the memory the pointer is pointing to is NOT freed. So you manually have to do

delete textures["string"];
textures.remove("string");

The syntax might be a little off.

Share this post


Link to post
Share on other sites
Syranide    375
Quote:
Original post by risingdragon3
I'm going to guess what Synranide is trying to say.

He has something like this:

std::hash_map<string, TextureClass*> textures;

and wants to know about what happens to the memory when you do

textures.clear();

for example. The answer to the question is that the memory the pointer is pointing to is NOT freed. So you manually have to do

delete textures["string"];
textures.remove("string");

The syntax might be a little off.


Yes that was in the right direction, however as of the later posts, the real concern with just hash_map was lost... which was very much the same... but the key... I really can't imagine people getting the reference to the key too and then freeing it... so, how do they handle the keys?

(Copy it internally (does it really work out practially? assuming arbitrary types/classes as key)? Assume ownership (as in if the caller wants to use it, he should create a clone first)?)

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by risingdragon3
I'm going to guess what Synranide is trying to say.

He has something like this:

std::hash_map<string, TextureClass*> textures;

and wants to know about what happens to the memory when you do

textures.clear();


Since he seems to concur with this...

The hash_map "owns" the pointer (not the object pointed at!). When you call clear(), the pointers are destroyed. Assuming that one wants the textures destroyed as well, one has a few options.

If you're using Managed C++ with GC, you can simply ignore the situation as the garbage collection cycle will delete the textures once nothing references them anymore.

For unmanaged C++, the most elegant solution is to use a smart pointer type. Basically, smart pointers are tools that help automatically deal with deletion. The standard library includes one such pointer, std::auto_ptr (note: this cannot be used in containers!!!). Basically, it allows one to write this without a memory leak:

void foo () {
std::auto_ptr< bar > my_ptr( new bar( ... ) );
my_ptr->bar_member_function();
//no call to delete, when my_ptr goes out of scope the pointed to object will be deleted!!!
}


auto_ptr is a very weird little critter in some other ways, however. Assigning one to another transfers ownership. The quirky nature of auto_ptr assignment is what disbars them from being usable in containers, you should get an error if you attempt to do so.

But auto_ptr is not the only smart pointer out there. I highly recommend The Boost C++ Libraries, including the boost smart pointer library. Similarly to std::auto_ptr, it handles automatic deletion:

void foo () {
boost::shared_ptr< bar > my_ptr( new bar( ... ) );
my_ptr->bar_member_function();
//no call to delete, when my_ptr goes out of scope the pointed to object will be deleted!!!
}


Boost's "shared_ptr"s, as their name implies, SHARE ownership of the pointed to object - the pointed to object wont be destroyed until all the shared_ptr s pointing at it have been. Unlike auto_ptr, it can also be stored in a container. This allows for code like so, without leaking:

hash_map< string , boost::shared_ptr< TextureClass > > textures;

void initialize_textures() {
boost::shared_ptr< TextureClass > texture( new TextureClass( .. ) );
textures[ "whatever" ] = texture;
}

void destroy_textures() {
textures.clear(); //destroys the shared_ptr[s], which will in turn destroy the TextureClass[es] which do not have otehr shared_ptr[s] pointing at them.
}


Share this post


Link to post
Share on other sites
Syranide    375
Yes, ok, that is what more or less what I assumed, but it's hard to get that kind of information sometimes.

So thanks both, I will look into those "pointers".

Share this post


Link to post
Share on other sites
Telastyn    3777
Quote:

Say just for instance we send a CString or LPSTR as a key...


Then yes, you'll be manually required to delete the LPSTR. You're using C++. Use C++ strings. C++ strings are regular classes, not pointers, and will thus be automatically deleted along with the pair.

[edit: and the smart pointers when pointers are really necissary]

Share this post


Link to post
Share on other sites
Fruny    1658
std::tr1 has unordered_set and unordered_map.

Why the names? I guess either because people already laid claims to hash_set and hash_map. Or because it better describes the behaviour (it's a map, which doesn't require an ordering criterion) rather than an implementation detail (hash tables vs. some other magic).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this