Whant can cause a runtime error in std::list::push_back()?

Started by
8 comments, last by Qw3r7yU10p! 19 years, 1 month ago
I'm storing several objects into a hash_map<string, CMyObject> and, from time to time (randomly, it seems) my code crashes when I'm inserting a new node into the hash_map using operator[]. For example, I have something like:

hash_map<string, CMyObject>    m_MyHashMap;

...

bool CMyObjectManager::AddObject(const string& Key, ...other params...)
{
    if (m_MyHashMap.find(Key) != m_MyHashMap.end())
        return false; // The key is already in use

    CMyObject* pObject = &m_MyHashMap[Key];

    ...operate on pObject using the other params the function receives...

    return true;
}



This generally works OK, but sometimes I get a runtime error when creating the new element. I traced it to a point where the hash_map's inner list tries to create a new node using a function called (IIRC) _BuyNode(), which returns an invalid pointer (0x00000000). What could cause such behaviour? I would be very grateful if you could give me a hand with this problem. It's driving me crazy!
Advertisement
Because I think you get the address before it is created. Try this:
m_MyHashMap[Key]; // Create the objectCMyObject* pObject = &m_MyHashMap[Key]; // Get the objectif( !pObject ) // you should check this ;)   abort();... Access ...
I will try it, but I don't think so... The fact is that this code does work most of the time, it's just ocasionally that it fails. Besides, as I said, when it stops on that line and I look a the call stack in the debugger I see the error comes from a node allocation returning a NULL pointer.

But I've tried so many things, that trying your suggestion won't hurt. Thank you very much for your answer.

Anybody else has another idea?

(BTW: In case it gives you a clue, I'm using the Visual C++ .NET 2003 compiler.)
That's odd then. I currently used a std::map in my OpenAL project and have had no problems with it. I just converted it over to a hash_map and it still works fine. I do something similar to you with a string and then a UDT (96 bytes). However, I use iterators to access the data. You can try that as well. An example would be:
bool CMyObjectManager::AddObject(const string& Key, ...other params...){    hash_map<string, CMyObject>::iterator itr = m_MyHashMap.find(Key);    if ( itr != m_MyHashMap.end())        return false; // The key is already in use    m_MyHashMap[Key];    itr = m_MyHashMap.find(Key);    if ( itr == m_MyHashMap.end())        abort(); // BIG problem then    itr->second.<member data here>    ...operate on pObject using the other params the function receives...    return true;}


If that still crashes for you, then I would be inclined to think that the error might be else where. That syntax is pretty much the same that I am working with and I have had no problems, so I do not think the problem could be with the hash_map and your UDT. I would also suggest that you verify thatthe Key is not equal to "", just in case.
Are you using the standard implementation of the STL (presumably on Visual C++?) If it's 6.0 you might want to consider uggrading to STLport, if it's VC++ 2003 then you may want to try something like Drew has mentioned above (using an iterator and std::find). It should work the same with for std::map too, because I don't think the standard implementation of the STL comes with std::hash_map. You are asking about std::list in the topic of the thread, and you mention std::map but reference to std::hash_map so I'll try give some general insight that I've accumulated.

The reason I ask about the compiler is that I ran into a problem similar to this one when I was using Visual C++ 6.0 a year or so back; I was never sure what exactly caused the problem, but it (seemed) to be dying at random places. As you may or may not know, Visual C++ 6.0 was released before the standard was finished and there are problems all throughout the STL in that version. Also a suggestion I was given, you might want to use a pointer as your key - like std::string* or char*. I know it may sound weird, but that might be the problem.

When you're stepping through the map sequentially (for removal) make sure that you store the position of the iterator in a temp and increment it. I'm not sure if this flaw (was it a flaw?) exists in later versions of Visual C++, or even in STLport, but there was a problem with it in 6.0.

Hope this has helped a bit.
-John "bKT" Bellone [homepage] [[email=j.bellone@flipsidesoftware.com]email[/email]]
Night Elf - your code looks OK. Sorry.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
How much memory are you using? I have had similar problems when writing applications with very large memory footprints. Sometimes, there just isn't enough memory to push a new object onto a stack, vector, list, etc. This causes run-time errors. If this is what's happening, I'm not sure how you would solve it though.
Quote:Original post by cwhite
How much memory are you using? I have had similar problems when writing applications with very large memory footprints. Sometimes, there just isn't enough memory to push a new object onto a stack, vector, list, etc. This causes run-time errors. If this is what's happening, I'm not sure how you would solve it though.


I don't see a problem could exist from pushing an object onto the stack, I'm not exactly sure how the STL handles changing the sizes of the containers but I'm sure that everything is added to the tail end unless you're using some sort of std::sort algorithm (or inserting). I'm using a my own hashing implementation for my memory manager because I just found that the std::map was a bit too bloat for the little container that I needed.
-John "bKT" Bellone [homepage] [[email=j.bellone@flipsidesoftware.com]email[/email]]
Quote:Original post by Night Elf
I will try it, but I don't think so... The fact is that this code does work most of the time, it's just ocasionally that it fails. Besides, as I said, when it stops on that line and I look a the call stack in the debugger I see the error comes from a node allocation returning a NULL pointer.

But I've tried so many things, that trying your suggestion won't hurt. Thank you very much for your answer.

Anybody else has another idea?

(BTW: In case it gives you a clue, I'm using the Visual C++ .NET 2003 compiler.)


First off all are you using std::hash_map? if you are in VC++ 7.1 its been deprecated you should be using new the version stdext::hash_map (yes there not the same implementation of hash_map std version is older), remember hash_map is currently an STL extension not yet part of the standard library so implementators can do what ever they want with the extensions and in VC++ 7.1 and above they have put all the extensions in stdext namespace.

Secondly don't rely on the dumb subscript operator for inserting new elements prefer using hash_map::insert it will tell you if an insertion failed via returning a pair of iterator & boolean the boolean tells you if insertion was success or a failure the iterator refers to where the new element was added e.g.

hash_map<string, CMyObject>    m_MyHashMap;typedef hash_map<string, CMyObject>::value_type;...bool CMyObjectManager::AddObject(const string& Key, ...other params...) {   if(m_MyHashMap.find(Key) != m_MyHashMap.end())        return false; // The key is already in use    if(!m_MyHashMap.insert(value_type(Key, newObject)).second) {       //handle the case when insertion failed    }}
Is CMyObject assignable?

This topic is closed to new replies.

Advertisement