c++ - Visual Studio 发布中令人费解的 STL 错误

标签 c++ optimization crash memory-corruption

我很确定这是 Visual Studio 2005 优化器中的错误。问题出在 STL 映射上。

相关代码如下:

MyMapIterator myIt = m_myMap.find(otherID);

if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_A)
{
    //Prints stuff.  No side-effects whatsoever.
}
else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B && myIt->second.foo == FOO_A)
{
    //Prints stuff.  No side-effects whatsoever.
}
else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B && myIt->second.foo == FOO_B && /*other meaningless conditions */)
{
    //Prints stuff.  No side-effects whatsoever.
}

在调试中完美运行,过去在发布时崩溃,禁用全局优化“修复它”现在,没有任何效果。我得到一个:

Microsoft Visual Studio C Runtime Library has detected a fatal error in [...]

Press Break to debug the program or Continue to terminate the program. 

这发生在最后一个 else if 的 first MyMapIterator::operator->

map 是空的,我知道 find 应该返回 end(),前两个比较结果有效。但不知何故,第三次 'myIt != m_myMap.end()' 返回 true,并执行了 && 的右侧。

许多其他地方都像这样失败,'myIt != m_myMap.end()' 的变体在同一个文件中返回 true,但对我来说,这是排除大多数其他可能性的地方。以前一直以为是缓冲区溢出,踩到我的图上了,但是回过头来看代码。我很肯定没有其他线程在踩它,这是 100% 可重现的。

那么,我要从这里做什么。这对性能一点也不敏感。我只需要它按应有的方式工作。任何选项都是可以接受的。是的,我知道我可以用迭代器相等性检查来包围整个事情,这不是最好的代码。关键是,它应该仍然有效,如果失败,其他任何方法都可以。

编辑

最后一个 else-if 不产生任何跳转!

    if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_A)
009270BE  mov         ecx,dword ptr [this] 
009270C4  add         ecx,0Ch 
009270C7  lea         eax,[ebp-90h] 
009270CD  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::end (8A21E0h) 
009270D2  mov         esi,eax 
009270D4  lea         edi,[myIt] 
009270D7  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::const_iterator::operator!= (8A2220h) 
009270DC  movzx       ecx,al 
009270DF  test        ecx,ecx 
009270E1  je          lux::Bar::DoStuff+0E4h (927154h) 
009270E3  lea         esi,[myIt] 
009270E6  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::iterator::operator-> (8A21F0h) 
009270EB  cmp         dword ptr [eax+8],1 
009270EF  jne         lux::Bar::DoStuff+0E4h (927154h) 
    {
         Stuff
    }
    else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_B)
00927154  mov         ecx,dword ptr [this] 
0092715A  add         ecx,0Ch 
0092715D  lea         eax,[ebp-98h] 
00927163  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::end (8A21E0h) 
00927168  mov         esi,eax 
0092716A  lea         edi,[myIt] 
0092716D  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::const_iterator::operator!= (8A2220h) 
00927172  movzx       edx,al 
00927175  test        edx,edx 
00927177  je          lux::Bar::DoStuff+17Ah (9271EAh) 
00927179  lea         esi,[myIt] 
0092717C  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::iterator::operator-> (8A21F0h) 
00927181  cmp         dword ptr [eax+8],2 
00927185  jne         lux::Bar::DoStuff+17Ah (9271EAh) 
    {
            //Stuff
     }
    else if (myIt != m_myMap.end() && myIt->second.userStatus == STATUS_C)
009271EA  mov         ecx,dword ptr [this] 
009271F0  add         ecx,0Ch 
009271F3  lea         eax,[ebp-0A0h] 
009271F9  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::end (8A21E0h) 
009271FE  mov         esi,eax 
00927200  lea         edi,[myIt] 
00927203  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::const_iterator::operator!= (8A2220h) 
00927208  lea         esi,[myIt] 
0092720B  call        std::_Tree<std::_Tmap_traits<unsigned __int64,lux::Foo,std::less<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,lux::Foo> >,0> >::iterator::operator-> (8A21F0h) 
    {
            //Stuff in the condition and after

最佳答案

我怀疑您在其他地方有代码,其中有缓冲区溢出。

此其他代码正在设法破坏已发布代码正在使用的内存。

在 Debug模式下,额外的内存填充将改变行为。

更改其他随机代码也会改变行为,因为它会改变事物的相对位置。

基本上,您需要检查大量代码或使用 BoundsChecker 等工具来查找错误。

专注于数组或任何原始指针数学。也可以使用已删除的指针。

如果写入不会导致崩溃的地方,这样的错误可以隐藏很长时间。出于同样的原因,它们经常神秘地消失。

关于c++ - Visual Studio 发布中令人费解的 STL 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/835814/

相关文章:

C++:读取字符串,转换为动态 int 数组

c++ - 如何加快 float 到整数的转换?

iphone - CALayerInvalidGeometry',原因: 'CALayer bounds contains NaN: [0 0; nan nan] crash in view

android - 我的应用程序在尝试禁用主页按钮时崩溃

c++ - 在 qt5 中使用 QSharedPointers 时出现段错误

c++ - 用户定义的推导指南是否涉及模板模板参数作为指南标准的模板

java - 在哪些情况下最好使用无条件 AND(& 而不是 &&)

macos - 如何符号化 Electron 崩溃日志

C# lambda 函数含义和 C++ 翻译

python - 为什么在 Cython 中写入 C 数组这么慢?