【问题标题】:std::map compare function and NULLstd::map 比较函数和 NULL
【发布时间】:2013-08-22 21:21:22
【问题描述】:

我为 std::map 编写了一个比较函数,因此我可以拥有自定义键类型。

std::map<GGString *, GGObject *, GGDictionaryMapCompare> _map;

...

class GGDictionaryMapCompare
{
public:
    bool operator()(GGString * lhs, GGString * rhs)
    {
        return strcmp(lhs->str(), rhs->str()) < 0;
    }
};

添加元素的代码:

GGObject *GGDictionary::addKeyObject(GGString *theKey, GGObject *theObject)
{
    if (theKey == NULL || theObject == NULL)
        return NULL;

    _map.insert(std::pair<GGString *, GGObject *>(theKey, theObject));

    return theObject;
}

导致崩溃的代码:

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);
}

堆栈跟踪:

#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*)

问题是 lhs 是 NULL。我从不在地图中插入 NULL,所以这不应该发生。知道为什么吗?还是我只是做错了比较功能?我可以防止获得 NULL,但似乎有问题,我不想治愈症状而不是问题。

谢谢

【问题讨论】:

  • 显示你在哪里添加元素。
  • 您能否发布一些有关您如何使用它和/或如何向地图添加元素的代码?我可以尝试重现该问题。我没有看到该代码有任何明显的问题,所以可能在实现中有些奇怪。
  • GGAutoRelease 是做什么的?
  • 你确定指针真的是 NULL 而不仅仅是无效吗?
  • 您确定没有在其他任何地方修改_map,例如带有无意的_map[foo],其中fooNULL

标签: c++ stl


【解决方案1】:

在这段代码中:

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);
}

您没有检查theKey 是否为NULL。因此,当在theKeymap 的任何元素上调用比较器时,您将取消对NULL 的引用。

要解决此问题,请尝试添加NULL 检查:

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);
}

希望这会有所帮助!

【讨论】:

  • 添加该代码并不能解决问题,仍然在同一个地方崩溃。
  • @RogerGilbrat- 你确定你传入的是 NULL 指针而不是垃圾指针吗?你能告诉我们坏指针是什么吗?
【解决方案2】:

不知道键比较函数是否应该修改成这样:

bool operator()(const GGString *&lhs, const GGString *&rhs)
{
    if (lhs == NULL || rhs == NULL)
    {
       return false;
    }
    return strcmp(lhs->str(), rhs->str()) < 0;
}

基本上我认为参数应该是 const 引用,并且函数应该防止取消引用 NULL 指针

【讨论】:

  • 它使比较变慢并且可能治愈症状。
  • 支持null 可能是个好主意,但这个函数并没有给出严格的弱排序。对于a任意一个值,comp(a, null)comp(null, a)都是false,也就是说所有的值都等价于null,因此所有的值都是等价的。
  • 改为:if (rhs == NULL) return false; if (lhs == NULL) return true;
【解决方案3】:

您确定在访问 NULL 时会发生崩溃吗?您正在地图中存储指针;是否有可能在将其中一个指针存储在地图中后删除了它?像这样的:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-27
    • 2017-07-28
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-28
    相关资源
    最近更新 更多