Thread: STL map problem

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    83

    STL map problem

    What's wrong with this code? It seems to work fine most of the time, but I'm getting EXC_BAD_ACCESS on some occasions.

    Here is the debug stack:

    Code:
    #4	0x00018016 in std::map<std::string, Item*, std::less<std::string>, std::allocator<std::pair<std::string const, Item*> > >::find at stl_map.h:542
    
    #3	0x00017f51 in std::_Rb_tree<std::string, std::pair<std::string const, Item*>, std::_Select1st<std::pair<std::string const, Item*> >, std::less<std::string>, std::allocator<std::pair<std::string const, Item*> > >::find at stl_tree.h:1378
    
    #2	0x00017efe in std::less<std::string>::operator() at stl_function.h:227
    
    #1	0x00002fff in std::operator< <char, std::char_traits<char>, std::allocator<char> > at basic_string.h:2228
    
    #0	0x97dab336 in std::string::compare
    Why would this crash on string compare? I've tried several variations on the format of the string being passed to find(), but can't get any of them to work.

    Thanks so much for your help!


    Code:
    // Group.h
    #include "Item.h"
    
    typedef map<string, Item*> GroupMap;
    
    class Group {
    public:
    	Group();
    	
    	void addItem(string name, Item* item);
    	Item* getItem(string name);
    
    protected:
    	GroupMap items;
    };
    
    // Group.cpp
    #include "Group.h"
    
    Group::Group() {}
    
    void Group::addItem(string name, Item* item) {
    	items.insert(pair<string,Item*>(name.data(),item));
    }
    
    Item* Group::getItem(string name){
    	GroupMap::iterator it;
    		
    	it=items.find(name.data());
    	if(it != items.end()) {
    		return (*it).second;
    	}
    	return NULL;
    }

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    If I had to guess...
    Code:
    Item* Group::getItem(string name){
    	GroupMap::iterator it;
    		
    	it=items.find(name.data());
    	if(it != items.end()) {
    		return (*it).second;
    	}
    	return NULL;
    }
    The data member function does not return a valid C style string... what it returns does not have a null terminator. I'm guessing this causes a problem when doing the find. Since the first member of the map is a std::string, there should be no problem using find with the std::string variable name directly.

    Code:
    it=items.find(name);
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Nov 2008
    Posts
    83
    Hey,
    Thanks.
    Unfortunately, that isn't the problem. I also tried find(name) and got the same results.

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    This:
    Code:
    return (*it).second;
    Usually looks better as:
    Code:
    return it->second;
    Also, this:
    Code:
    void Group::addItem(string name, Item* item) {
    	items.insert(pair<string,Item*>(name.data(),item));
    }
    Has the same problem I mentioned in the earlier post.


    ...it's been awhile since I've used maps. That may or may not be a source of your problems in debugging.

    [edit]Post the newest code you've got once you've made the changes.[/edit]
    Last edited by hk_mp5kpdw; 01-19-2011 at 11:34 AM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Did you fix it in items.insert() as well? I'm a bit confused as to why your backtrace doesn't go down into your actual code.

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    83
    Hi,
    Thanks for your help. Here is the modified code. Still produces the same problem.

    Code:
    // Group.h
    #include "Item.h"
    
    typedef map<string, Item*> GroupMap;
    
    class Group {
    public:
    	Group();
    	
    	void addItem(string name, Item* item);
    	Item* getItem(string name);
    
    protected:
    	GroupMap items;
    };
    
    // Group.cpp
    #include "Group.h"
    
    Group::Group() {}
    
    void Group::addItem(string name, Item* item) {
    	items.insert(pair<string,Item*>(name,item));
    }
    
    Item* Group::getItem(string name){
    	GroupMap::iterator it;
    		
    	it=items.find(name);
    	if(it != items.end()) {
    		return it->second;
    	}
    	return NULL;
    }

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Are you using gdb? Can you go up (as many times as necessary) until you get to your code? That would give you information like (1) what line we're on in your code (2) what the values of the variables like name and item and things are.

  8. #8
    Registered User
    Join Date
    Nov 2008
    Posts
    83
    Hey,
    Sorry, here is a more complete backtrace:

    Code:
    #6	0x00012085 in GroupController::getInfo at GroupController.cpp:128
    NOTE: here is what the calling method looks like...
    void GroupController::getInfo() {
    	Item* myItem = theGroup->getItem("Info");
    	// ... nothing else in this function relates to the problem...
    }
    
    #5	0x000176f3 in Group::getItem at Group.cpp:22
    NOTE: Group.cpp:22 is "it=items.find(name);"
    
    #4	0x00018016 in std::map<std::string, Item*, std::less<std::string>, std::allocator<std::pair<std::string const, Item*> > >::find at stl_map.h:542
    
    #3	0x00017f51 in std::_Rb_tree<std::string, std::pair<std::string const, Item*>, std::_Select1st<std::pair<std::string const, Item*> >, std::less<std::string>, std::allocator<std::pair<std::string const, Item*> > >::find at stl_tree.h:1378
    
    #2	0x00017efe in std::less<std::string>::operator() at stl_function.h:227
    
    #1	0x00002fff in std::operator< <char, std::char_traits<char>, std::allocator<char> > at basic_string.h:2228
    
    #0	0x97dab336 in std::string::compare
    thanks again. weird problem... can't make sense of it.

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    There is no problem in the last code snippet you posted so the problem is elsewhere.

    Please try and make a minimal but complete compileable example program that produces the problem.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Are you perhaps accessing a NULL pointer in your GroupController::getInfo method returned from that call to getItem? Do you have guards against that?
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  11. #11
    Registered User
    Join Date
    Nov 2008
    Posts
    83
    Thanks again for your help.
    I believe the problem has to do with the string I'm passing to find() in the method getItem().
    Within my program, getItem() is often evoked during a callback event. It's only in these cases that the find function crashes. I have the suspicion that the string can't be accessed properly during the event callback because the string is already being accessed from somewhere else? I'm not doing any threading, but is it possible that my callback events could cause similar problems to thread accessing of strings? Is there any way I can test this? Would making some sort of copy of the string help at all? Sorry for my confusion... can't make head or tail of this problem.

  12. #12
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You're passing the string by copy anyway. Again, if you type "up" five times (assuming you're running this in GDB, or are attaching GDB to it), you can see exactly what name and all your other variables are (by doing "print name" or "print Item" etc.). So do that, and you'll know whether you're getting passed garbage or what.

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you are not using threading then nothing else is accessing the string at the same time this method is. I would prefer to pass the string via const reference. I highly doubt the string is the problem as I've used this same type of map thousands of times with no trouble. I suspect some object is using the map and not checking if the get returns null. It would be wise to allow the add function to return a boolean. Insert returns a pair<iterator,bool>. The iterator is the insertion point and the bool indicates if the operation was successful or not.
    Last edited by VirtualAce; 01-19-2011 at 06:19 PM.

  14. #14
    Registered User
    Join Date
    Nov 2008
    Posts
    83
    Oh, thanks.

    Here is what print name gives back:

    Code:
    // WITHOUT CALLBACK EVENT
    $1 = {
      static npos = 4294967295, 
      _M_dataplus = {
        <std::allocator<char>> = {
          <__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, 
        members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider: 
        _M_p = 0x1b0d05c "a"
      }
    }
    
    // WITH CALLBACK EVENT
    $1 = {
      static npos = 4294967295, 
      _M_dataplus = {
        <std::allocator<char>> = {
          <__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, 
        members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider: 
        _M_p = 0x342174a9 <Address 0x342174a9 out of bounds>
      }
    }
    How can I fix this?

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If this came from a callback, then up one more level on your call stack had better be, therefore, the function where the callback is happening. Go there, and look around, and see why it's passing basically a bad string to you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help me figure out how to use STL map containers
    By Bozebo in forum C++ Programming
    Replies: 2
    Last Post: 01-07-2011, 09:48 PM
  2. STL Map Problem with user defined Class
    By noobcpp in forum C++ Programming
    Replies: 21
    Last Post: 07-21-2008, 12:02 PM
  3. Replies: 4
    Last Post: 05-25-2008, 12:31 AM
  4. map problem
    By l2u in forum C++ Programming
    Replies: 1
    Last Post: 10-29-2006, 06:06 PM
  5. STL map with D3DXVECTOR2 as key help.
    By Pazu in forum C++ Programming
    Replies: 1
    Last Post: 03-14-2006, 11:15 AM