我的问题有点复杂,但我试图简单地描述它。我想在我的一个类中使用本地静态成员(类型std::map<std::string, std::weak_ptr>
)实现一个静态方法。每次调用此方法时,它都应该查找映射中是否存在以传递的参数为键的对象。该方法返回的值是一个std::shared_ptr
(从std::weak_ptr
地图中的 构造,如果std::weak_ptr
可以锁定 - 否则std::shared_ptr
构造一个新的并添加std::weak_ptr
到std::map
)。但是我在拨打电话的线路上“有时”会收到访问冲突std::map.find()
。
“有时”的意思是:如果一个std::weak_ptr
被添加到地图中,然后因为它无法被锁定而被删除 - 并且一个新std::shared_ptr
的被构建,添加std::weak_ptr
到std::map
. 下次我的静态方法尝试在std::map
其中查找时,可能(偶尔)来自以下位置的访问冲突:
File: Microsoft Visual Studio 11.0\VC\include\xtree
Line: 2092
Method: _Nodeptr _Lbound(const key_type& _Keyval)
Access Violation at reading: '_Nodeptr _Pnode = _Root();'
我找不到任何方法来更好地调试问题 - 非常感谢这里的任何帮助。
最后但并非最不重要的一点是,我重写了一些代码,以获得一个简短的、不言自明的示例。但到目前为止,我无法在这里重现访问冲突。
#include <map>
#include <memory>
#include <string>
#include <iostream>
class MyClass{
public:
MyClass(int a){
this->a = a;
}
virtual ~MyClass(){ }
private:
int a;
};
class MyStaticClass{
public:
static std::shared_ptr<MyClass> myMethod(const char* string){
static std::map<std::string, std::weak_ptr<MyClass>> map;
std::shared_ptr<MyClass> retVal = nullptr;
std::map<std::string, std::weak_ptr<MyClass>>::iterator iter = map.find(std::string(string));
if(iter != map.end()){
retVal = iter->second.lock();
if(!retVal){
/* ptr is gone already, so remove it from map */
iter = map.erase(iter);
}
}
if(!retVal){
/* not found in map OR erased - need to be created again */
retVal = std::make_shared<MyClass>(atoi(string));
std::weak_ptr<MyClass> weakRetVal = retVal;
map.insert(std::make_pair(std::string(string), weakRetVal));
}
return std::move(retVal);
}
};
int main(int argc, char* argv[]){
{
std::shared_ptr<MyClass> myIntPointer = MyStaticClass::myMethod("1");
}
{
std::shared_ptr<MyClass> myIntPointer = MyStaticClass::myMethod("1");
}
{
std::shared_ptr<MyClass> myIntPointer = MyStaticClass::myMethod("1");
}
return 0;
}
编译器/平台:VS 2012 / Windows 8
编辑:到目前为止,我发现,当这个错误发生时,'map' 的大小总是再次为 0(至少根据调试器)。因此,即我以未初始化的地图启动程序(当然大小为0)。然后使用 myMethod() 添加条目 - 映射的大小为 4。现在 std::weak_ptr 到期,我再次调用 myMethod()。调试器现在显示 map.size() 将再次为 0(永远不会删除映射条目,因此这应该是不可能的)。
Edit2:当大小应该是 0x00000004 时,调试器也会显示 0xff000004 作为大小(当然大多数“条目”都不能显示)。本地静态存储是否存在任何 32 位/64 位问题?