Reputation: 3835
I've written a compare function for a std::map so I can have custom key types.
std::map<GGString *, GGObject *, GGDictionaryMapCompare> _map;
...
class GGDictionaryMapCompare
{
public:
bool operator()(GGString * lhs, GGString * rhs)
{
return strcmp(lhs->str(), rhs->str()) < 0;
}
};
Code that adds elements:
GGObject *GGDictionary::addKeyObject(GGString *theKey, GGObject *theObject)
{
if (theKey == NULL || theObject == NULL)
return NULL;
_map.insert(std::pair<GGString *, GGObject *>(theKey, theObject));
return theObject;
}
Code that is causing the crash:
GGObject *GGDictionary::objectForKey(GGString *theKey)
{
if (theKey == NULL)
return NULL;
std::map<GGString *, GGObject *, GGDictionaryMapCompare>::iterator ii = _map.find(theKey);
if (ii == _map.end())
return NULL;
return GGAutoRelease(ii->second);
}
Stack trace:
#0 0x00009f15 in GGString::str()
#1 0x0004a4c4 in GGDictionaryMapCompare::operator()(GGString*, GGString*)
#2 0x0004a3d3 in std::_Rb_tree<GGString*, std::pair<GGString* const, GGObject*>, std::_Select1st<std::pair<GGString* const, GGObject*> >, GGDictionaryMapCompare, std::allocator<std::pair<GGString* const, GGObject*> > >::find(GGString* const&)
#3 0x00049b04 in std::map<GGString*, GGObject*, GGDictionaryMapCompare, std::allocator<std::pair<GGString* const, GGObject*> > >::find(GGString* const&)
#4 0x00048ec9 in GGDictionary::objectForKey(GGString*)
The issue is that the lhs is coming in NULL. I never insert a NULL into the map, so this should not be happening. Any idea why? Or am I just doing the compare function wrong? I can protect against getting NULL, but it seems like something is wrong and I don't want to cure a symptom and not the problem.
Thanks
Upvotes: 3
Views: 1935
Reputation: 5897
Are you sure the crash happens when accessing NULL? You are storing pointers in the map; is it possible that you deleted one of the pointers after storing it in the map? Something like this:
dict->addKeyObject( key1, obj1 );
delete key1; // now dict has a pointer to deleted key1
dict->addKeyObject( key2, obj2 ); // now dict will compare key2 to key1, causing crash
Upvotes: 0
Reputation: 71
I wonder if the key compare function should be revised to something like this:
bool operator()(const GGString *&lhs, const GGString *&rhs)
{
if (lhs == NULL || rhs == NULL)
{
return false;
}
return strcmp(lhs->str(), rhs->str()) < 0;
}
Basically I'm thinking the parameters should be const references, and also that the function should protect against dereferencing NULL pointers
Upvotes: 0
Reputation: 372814
In this code:
GGObject *GGDictionary::objectForKey(GGString *theKey)
{
std::map<GGString *, GGObject *, GGDictionaryMapCompare>::iterator ii = _map.find(theKey);
if (ii == _map.end())
return NULL;
return GGAutoRelease(ii->second);
}
You aren't checking whether theKey
is NULL
. Accordingly, when the comparator is invoked on theKey
and any element of the map
, you will dereference NULL
.
To fix this, try adding in a NULL
check:
GGObject *GGDictionary::objectForKey(GGString *theKey)
{
if (theKey == NULL) return NULL;
std::map<GGString *, GGObject *, GGDictionaryMapCompare>::iterator ii = _map.find(theKey);
if (ii == _map.end())
return NULL;
return GGAutoRelease(ii->second);
}
Hope this helps!
Upvotes: 5