在成员函数(C ++ 11 / STL)中使用本地静态std :: map <std :: string,std :: weak_ptr =“”>访问冲突</std :: string,>

时间:2013-09-28 17:51:36

标签: c++ c++11

我的问题有点复杂,但我试着简单地描述它。 我想在我的一个类中使用本地静态成员(类型为std::map<std::string, std::weak_ptr>)实现静态方法。每次调用此方法时,都应该查看地图中的对象是否将传递的参数作为键。方法返回的值是std::shared_ptr(如果std::weak_ptr可以锁定,则从地图中的std::weak_ptr构建 - 否则构建新的std::shared_ptr并且已添加为std::weak_ptr的{​​{1}}。但我收到的“有时”访问违规行为是我拨打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();'

编译器/平台:VS 2012 / Windows 8

编辑:我发现到目前为止,当发生此故障时,'map'的大小始终为0(至少根据调试器)。所以即我开始使用地图未经注册的程序(当然大小为0)。然后使用myMethod()添加entrys - 地图的大小即4.现在std :: weak_ptr到期,我再次调用myMethod()。调试器现在显示map.size()将再次为0(映射entrys永远不会删除,所以这不可能)。

Edit2:当大小应为0x00000004时,还有一种情况,调试器显示0xff000004作为大小(当然,大多数“条目”无法显示)。本地静态存储是否会涉及32位/ 64位问题?

1 个答案:

答案 0 :(得分:1)

我发现了我的问题的解决方案,就像来自不同代码段的堆栈/堆损坏中的注释所暗示的那样。万一有类似问题的人有一天会发现这个问题,我将简要介绍一下究竟出了什么问题以及我找到原因的步骤。

1。)因为我在使用普通全局函数和全局静态std :: map时没有遇到这个问题,所以它表明在类似的存储范围(本地函数静态)中存在问题。在使用全局静态std :: map时,我没有发生访问冲突的原因很简单,我的堆栈/堆损坏与另一个类中的不同本地函数静态对象一起发生。因此,对于具有不同存储范围的副作用(即本地函数静态VS全局静态),对同一存储范围内的对象的副作用更可能。

2。)我刚刚执行了很多次代码,以便在确切地发生访问冲突时识别模式,以及我的步骤是重现该行为。然后我注意到,如果我按下键盘上的键,我的访问违规行为会增加规律性。这对我来说似乎已经是一个非常奇怪的副作用了,让我特意检查了我的输入课程。

3.)我找到了致命的代码: 我对我的一个输入类使用了单例方法(这意味着:该类有一个静态的getInstance()方法,该方法返回类本身的本地函数静态对象)。提醒一下:我的访问冲突也发生在本地函数静态对象上。非常怀疑......在深入了解这个类的过程中,我找到了一个将实际键值存储在数组中的成员。使用一些模糊的宏来声明数组大小,这些宏被解析为简化为:

unsigned char keyValues[sizeof(unsigned short)];

但当然sizeof()运算符不返回类型的最大值 - 而是返回字节大小(即x86和x64上的2 - 或者在某些情况下由于对齐而为4)。因此,如果我将sizeof(unsigned short)替换为65536(或USHRT_MAX <climits>),我的代码运行clenaly而没有任何访问violtion ...... :(愚蠢的错误导致致命的后果......