Skip to main content
gamedev.net
🔒 Locked

std::map std::string, std::string - cannot find( )

Started by kordova 17 replies 6k views
Original Post
kordova
kordova
I have spent so much time away that it took me a minute to find the "new thread" button. Anyway... I have the following code:

typedef std::map< std::string, std::string, std::less< std::string > > HASH;
HASH _hash;
_hash[ std::string( "yahar" ) ] = std::string( "blah" );
HASH::const_iterator it;
// Below prints 'yahar => blah'
for (it = _hash.begin(); it != _hash.end(); ++it) 
  printf( "%s => %s\n", it->first.c_str( ), it->second.c_str( ));

HASH::iterator iter;
iter = _hash.find( std::string( "test" ));
if ( iter != _hash.end( )) {
  return ( *iter ).second;
}


At the _hash.find( ) call the application exits with a signal 11 SIGSERV. When I remove the "yahar" line, it simply continues along happily. Of note, gdb throws me in basic_string.h (in a std::string::compare call). It appears as though it is comparing the empty string (lhs) to "test"(rhs). I must be doing something strange above.
Doggan
Doggan
std::string( 'test' ) == std::string( "test" ) ??
kordova
kordova
Sorry, a python/ruby habit. That should be "test".
Doggan
Doggan
Aside from the correction already made, that is the correct usage of std::map find. Given a key, it will return the iterator of the first key with that value (the only key of that value in the case of a map) or end().

The code compiles and runs fine on VC++ 2005. That error would signify accessing NULL memory. What version of GCC (I'm assuming) are you running? Did you install everything correctly? o_O
jflanglois
jflanglois
The problem has to do with your not returning anything on failure to find an item in the map. You need to either return a default constructed string or throw. (edit: I have the impression gdb mislead you)

Apart from that:
- note that you do not need to specify std::less< std::string > in your typedef; that is the default.
- you can pass in string literals where std::string is expected. No need to explicitly instanciate an std::string.
- (Only a suggestion) use std::cout instead of printf(), it's safer and idiomatic.

So, you total is:

Return default constructed:
typedef std::map< std::string, std::string > HASH;HASH _hash;_hash["yahar"] = "blah";HASH::const_iterator it;// Below prints 'yahar => blah'for (it = _hash.begin(); it != _hash.end(); ++it)   std::cout << it->first << " => " << it->second << std::endl;HASH::iterator iter;iter = _hash.find( "test" );if( iter == _hash.end() )  return std::string();else return ( *iter ).second;


Throw:
typedef std::map< std::string, std::string > HASH;HASH _hash;_hash["yahar"] = "blah";HASH::const_iterator it;// Below prints 'yahar => blah'for (it = _hash.begin(); it != _hash.end(); ++it)   std::cout << it->first << " => " << it->second << std::endl;HASH::iterator iter;iter = _hash.find( "test" );if( iter == _hash.end() )  throw std::runtime_error( "string not found" );return ( *iter ).second;


jfl.
kordova
kordova
gcc 4.0.1 (using Xcode on Mac)
kordova
kordova
Quote:
Original post by jflanglois
The problem has to do with your not returning anything on failure to find an item in the map. You need to either return a default constructed string or throw.

I apologize, I did not include the complete code listing.

I am positive that the problem is from within the call to find (I am stepping through with the debugger).

Quote:
Original post by jflanglois
Apart from that:
- note that you do not need to specify std::less< std::string > in your typedef; that is the default.
- you can pass in string literals where std::string is expected. No need to explicitly instanciate and std::string
- (Only a suggestion) use std::cout instead of printf()
Thank you for the input.
jflanglois
jflanglois
Quote:
Original post by kordova
I apologize, I did not include the complete code listing.

Well then, may we see the entire listing?
kordova
kordova
Quote:
Original post by jflanglois
Quote:
Original post by kordova
I apologize, I did not include the complete code listing.

Well then, may we see the entire listing?

Here it is:
// Called with std::string( "test" )bool hasKey( const std::string &key ) {  HASH::const_iterator it;  for (it = _configHash.begin(); it != _configHash.end(); ++it)     printf( "%s => %s\n", it->first.c_str( ), it->second.c_str( ));    HASH::iterator iter;  // gdb signal EXC_BAD_ACCESS below in std::string::compare  iter = _configHash.find( std::string( "test" ));  return iter != _configHash.end( );}


EDIT:
Ok, so doing a clean and then rebuild in xcode left this building...

I am inclined to return to makefiles as I am uncertain as to why that was necessary to build this properly...

In any event, thanks for your time and patience, it was quite helpful to my understanding.
jflanglois
jflanglois
Oh good. I was out of suggestions. :)
kordova
kordova
Hmmm, this is bizarre. It only actually works if I instantiate a HASH object and assign a value to it in my main function (before instantiating the class with method hasKey). If I remove the main hash object (or the assignment of any value to a key) from the code, I get that error...

EDIT:
Doing:
CP * cp = new CP( arg );
fixes it where as before I used:
CP cp( arg );
kordova
kordova
Ultimately, I want to integrate boost into this project. I am interested in embedding python, using the boost unit test framework, in particular.

When I do:
CP cp( arg );

I get the bad access exception as stated above;

When I do:
CP *cp = new CP( arg );

Everything works as is expected. Quite strange;
jflanglois
jflanglois
Well then I can only suggest that you step into find() to pinpoint the cause. Unfortunately, I have access to neither xcode nor GCC 4.0.1, so I can't test it myself.
kordova
kordova
I rebooted into windows, ran this in VS 2003 without incident. I am chalking this up to my misconfiguration or misunderstanding of xcode for now.
daerid
daerid
There's something funky going on. I used xcode for 6 months and never ran into anything like that.
daerid@gmail.com
kordova
kordova
Soemthing funky indeed. This morning I copied the two class files into a new project and they ran smoothly. I removed them from xcode in the main project, readded them and compiled and now it works. Meh.
Zakwayda
Zakwayda
FWIW, I run into these sorts of problems using Xcode occasionally as well. It might just be because I don't know what I'm doing, but it seems that Xcode doesn't always update .o files when it should, leading to crashes and other seemingly inexplicable behavior.

A clean and rebuild, although tedious, always seems to solve the problem for me.
kordova
kordova
Actually it is worth something as a similar problem happened to me a few minutes ago again. Make clean does not seem to fix it, but exiting xcode and then reopening it does. I am not really certain what is going on.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.