C++ 不可能的事件顺序

C++ 不可能的事件顺序,c++,visual-c++,C++,Visual C++,我试图在for循环中追踪一个神秘的迭代器问题。我在迭代器的操作符中得到一个错误=这通常意味着被比较的迭代器不属于同一个容器。追踪微软实现的库,操作符=调用运算符==,其中此测试为真: bool operator==(const _Myiter& _Right) const { // test for iterator equality #if _ITERATOR_DEBUG_LEVEL == 2 if (this->_Getcont()

我试图在
for
循环中追踪一个神秘的迭代器问题。我在迭代器的
操作符中得到一个错误=
这通常意味着被比较的迭代器不属于同一个容器。追踪微软实现的库,
操作符=调用
运算符==
,其中此测试为真:

    bool operator==(const _Myiter& _Right) const
        {   // test for iterator equality
 #if _ITERATOR_DEBUG_LEVEL == 2
        if (this->_Getcont() == 0
            || this->_Getcont() != _Right._Getcont())
            {   // report error
            _DEBUG_ERROR("list iterators incompatible");
为了获取更多信息,我编写了这个小函数来替换我的
=for
循环中的code>:

template<typename iter>
bool bang_equal(const iter & left, const iter & right)
{
   static int count = 0;
   auto p1 = left._Getcont();
   auto p2 = right._Getcont();
   ATLTRACE("Iterator comparison left _Getcont()=%p right _Getcont()=%p %d\n", p1, p2, ++count);
   MemoryBarrier();
   bool b = left != right;
   MemoryBarrier();
   auto p3 = left._Getcont();
   auto p4 = right._Getcont();
   ATLTRACE("                    left _Getcont()=%p right _Getcont()=%p %d\n", p3, p4, ++count);
   return b;
}

查看“反汇编”窗口以预期顺序显示说明。我被难住了。可能会发生什么?

我的直觉告诉我,这里最有可能的解释是Occam的razor:特别是在迭代过程中使迭代器无效。事实上,for循环中没有
++iter
,这进一步强调了它不是对每个元素的直接迭代

它可能不直接在循环内部,但容器很可能在从循环体调用的调用链中的某个位置出现别名-这些都是非常容易犯的错误,而且诊断起来非常残酷。您至少应该在每次迭代时打印容器的大小


如果您可以访问Linux,并且代码中有足够小的部分可以重现问题,那么您也可以利用valgrind来帮助您解决这个问题。

最终解决了这个问题。Microsoft函数“调试”消息将显示一个对话框,询问您是否要中止、重试(调试)或忽略错误。当对话框显示时,消息pump仍然在运行,允许进行其他活动。我的函数再次被调用,这次它运行完成,在这个过程中生成了大量调试输出。如果我在库代码中的
\u DEBUG\u ERROR
行上放置一个显式断点,我将捕获错误,而不在后台执行其他操作。事后回想一下调试输出,我可以看到预期的错误输出确实存在,只是埋藏得太深,我从未见过它。

显示您正在使用的代码!=。99.9%或更多的奇怪错误是用户错误,而不是实现错误。马克,我知道我们不需要从你的基础开始,但请幽默我。我在代码中没有看到显式断点,所以我假设这是您在调试器中添加的断点。你试过“重建所有”吗?你是在调试还是发布版本中尝试这一点?我检测到原力中有一种干扰,比如一组数据被数组溢出尖叫声重击,然后突然变得沉默。我猜您的代码中的其他地方有一个内存损坏错误,导致了这种行为:)@NikBougalis,断点在
\u DEBUG\u ERROR
code:
:\u crtdbgbbreak()。这是一个调试版本,是的,我做了一个重建所有。我会再做一次,只是为了确定。@Michael:+1作为《星球大战》的参考。另外,一个很有前途的理论,如果不太可能的话(马克知道他做的什么是对的?),或者你可以设置一个硬件断点,当你感兴趣的内存发生变化时触发;)@Nik Bougalis OP指出,所讨论的元素在每次运行时都会发生更改,因此我认为数据断点在这里没有帮助。啊。。。我早该弄明白的。我以前被这个咬过。微软的设计太糟糕了。我记得现在也处于同样的情况。。。不止一次。
Iterator comparison left _Getcont()=07D0B2C8 right _Getcont()=07D0B2C8 2984
                    left _Getcont()=07D0B2C8 right _Getcont()=07D0B2C8 2985
Myprog.exe has triggered a breakpoint.