tags:

views:

720

answers:

10

So, I have this situation where I need to see if an object is in my stl map. If it isn't, I am going to add it.

char symbolName[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
map<string,TheObject> theMap;
if (theMap.find(symbolName)==theMap.end()) {
      TheObject theObject(symbolName);
      theMap.insert(pair<string, TheObject>(symbolName,
        theObject));
}

I am getting a core dump on the: theMap.find when the object is not already in the map. Supposedly, if the item is not in the map, it is supposed to return an iterator equivelent to map::end

What is going on here?

GCC: 3.4.6

+1  A: 

This code should work fine.

The only possible problem is inside TheObject implementation, but it shouldn't affect the find call.

Also, can be some unrelated issue, like Buffer overflow due to some code executed before it.

Igor Oks
It doesn't work though. Codelogic mentioned that there might be a problem if the tree is empty to start, but I am not sure why.
windfinder
Can you add the definition of TheObject class? And what compiler are you using?
Igor Oks
I cannot add a definition of the class. Version of the compiler is gcc 3.4.6
windfinder
+1  A: 

Check whether your STL map is empty() before doing a find(). Some STL implementations are buggy when executing a find() on an empty STL map.

codelogic
It is almost certainly empty. Is this a problem? Why?
windfinder
I have my doubts as to how often this shows up, but this thread talks about something like this: http://www.velocityreviews.com/forums/t278300-stdmapfind-throws-exception-when-map-is-empty.html
Eclipse
+4  A: 

Why not just do it this way?

char symbolName[] = "hello";
theMap.insert(pair<string, TheObject>(symbolName, TheObject(symbolName)));

If your map is a map<string, TheObject> then you WILL get a core dump if you try to search for NULL:

// This will core dump:
char *symbolName = NULL; // Oops!
theMap.find(symbolName); // Kabang!
Eclipse
if just insert TheObject(symbolName) and there is already an instance of TheObject for that symbolName, then it will overwrite it.
windfinder
No, if the key is already there, insert won't do anything (indicated by false in the second value in the returned pair.)
Eclipse
+1 Nice one Josh - why write all the extra code when STL will do the check for you
hamishmcn
+2  A: 

By the way, there are two possible simplifications.

First, use make_pair instead of using the pair constructor. This means you don't have to specify the type arguments explicitly:

theMap.insert(make_pair(symbolName, theObject));

Second, instead of your code you can simply write:

theMap[symbolName] = theObject;
Konrad Rudolph
IIRC, accessing an STL map using the bracket operator if the key doesn't exist in the map returns NULL or throws an exception -- either way, the end result of the assignment is you get an exception.
rmeador
No - it will create the entry if needed using the values default constructor.
Eclipse
@rmeador: no. The bracket operator has this very important and widely ignored side-effect. It's the reason why there's no `const` version of this operator, a fact that irritates people to no ends.
Konrad Rudolph
it will, however, overwrite any previously stored TheObject object. if it has mutable state, it may change matters.
Johannes Schaub - litb
I stand corrected, having just read the docs... I also know that I ran into the situation I described in my first comment. The only explanation I can think of is that the type I had in my map didn't have a default constructor, but I question whether that would compile at all...
rmeador
+2  A: 

Post your real code, or at least a complete example that exhibits the behavior you're describing. Sometimes the problem is a subtlety lost in the translation when you try to debug make-believe code written just to post in forums like this.

Ben Collins
+4  A: 

It can crash because of many reasons. Without knowing the definition of at least TheObject's constructors, i think we are largely left to guess at the problem. So far, your code looks fine, but it can be simplified:

char symbolName[] = "Hello";
map<string,TheObject> theMap;
theMap.insert(make_pair(symbolName, TheObject(symbolName)));

It won't do anything if the symbol is already mapped, discarding the new TheObject object.

Johannes Schaub - litb
Unless, of course, TheObject is heavy to construct.
dalle
A: 

I don't know why you get a core dump; the code works for me.

There are opportunities to make your code simpler and more readable:

  • As someone else noted, you can simplify the insertion to theMap[symbolName] = TheObject(symbolName)

  • I might be wrong, but as far as I know { 'a', 'b', '\0' } is the same as "abc", so you could simplify to char symbolName[] = "Hello"; I have the impression that the non-idiomatic definition is confusing some people here.

Roel Schroeven
+1  A: 

As addition to the code simplifications:

Use std::string instead of char[] and use it inside of your class definition for TheObject too.

Not sure what your TheObject class is doing w/ the char array, but if you use the map outside of the scope of this function, eg. by using it as return value, i bet there is somewhere an object pointing to the adress of symbolName, which is not defined anymore.

A: 

Check if you are using it in a constructor. I had a similar problem when using map inside constructor.

A: 

I fixed my problem like this by using pointers to my map objects. Since used in constructor, they needed to be pointers and then inside constructor I new'ed them .