通过hash_map迭代AV?

时间:2009-09-29 17:46:17

标签: c++ stl hashmap access-violation

_transaction是我的类的私有成员变量,声明为:

public:
    typedef stdext::hash_map<wchar_t*, MyClass*, ltstr> transaction_hash_map; 
private:
    transaction_hash_map _transactions;

在清理过程中,我试图遍历此列表并释放任何仍然不同意的对象。但是我在这里 行获得AV:

for (transaction_hash_map::const_iterator it = _transactions.begin(); it != _transactions.end(); it++)
{   
            MyClass* item = (MyClass*)it->second;

    if (item != NULL)
    {
        item->End();
        delete item;
    }       
}

回复:什么是ltstr?

private:
    struct ltstr
    {
        enum
        {
            bucket_size = 8,
            min_buckets = 16
        };

        bool operator()(wchar_t* s1, wchar_t* s2) const
        {
            return wcscmp( s1, s2 ) < 0;
        }

        size_t operator()(wchar_t *s1) const
        {
            size_t  h = 0;

            wchar_t *p = const_cast<wchar_t*>(s1);
            wchar_t zero = L'\0';

            while ( *p != zero ) h = 31 * h + (*p++);

            return h;
        }
    };

堆栈在begin()方法中显示它。有什么想法吗?

3 个答案:

答案 0 :(得分:0)

据我所知,你正在检查你的指针是否为NULL,因为“剩余”项目可能还没有被删除。但是对于在清理阶段之前删除的项目,是否将指针设置为NULL?

请注意,删除对象时,指针会自动设置为NULL。因此,如果您没有这样做,那么您尝试删除相同的对象两次(因为您的if语句将始终为true),可能会导致访问冲突。

以下代码是导致双重删除的示例。如果取消注释将指针设置为NULL的行,则可以修复它。


#include <cstddef>

struct Item {};

int main()
{
  Item * p = new Item();
  delete p;

  //If you don't make the pointer null...
  //p = NULL;

  if (p != NULL)
      //You delete the object twice.
      delete p;
}

编辑:我发现您的 行确实出现了错误。所以我想知道......

显然你有一个 MyClass ,它包含一个 _transactions 成员,这是一个以 MyClass 指针作为数据类型的哈希表。如果清理代码是在 MyClass 的成员函数内执行的,那么您是否可能删除(由于某种原因)拥有 MyClass 实例_transactions 你在迭代吗?

在这种情况下,您可能会在 for 中的 it ++ 语句中收到错误,因为对象不再存在。 (当然,错误也可能在其他地方,就像删除本身一样。)

答案 1 :(得分:0)

我可以想到的一件事是,在尝试迭代hash_map之前,你的类已经被删除了,因此begin()将在垃圾上运行。值得一试......

另外 - 你的wchar_t *如何被分配/释放?您显示的代码似乎没有处理这些代码。我不确定这会如何在你的循环中引起麻烦,但值得考虑。

一件小事 - 你不应该需要(MyClass*)演员表。无论如何,hash_map的值应该是该类型的,因此让编译器强制执行类型检查比使用显式强制转换可能绕过它们更好。这不应该在这里有任何区别。

答案 2 :(得分:0)

确保在for循环后调用_transactions.clear()。

相关问题