我试图在for循环中追踪一个神秘的迭代器问题.我在迭代器中得到一个错误,operator!=这通常意味着被比较的迭代器不属于同一个容器.跟踪Microsoft的库实现,operator!=调用operator==此测试的位置:
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");
Run Code Online (Sandbox Code Playgroud)
为了获得更多信息,我写了这个小函数来替换我!=在for循环中:
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;
}
Run Code Online (Sandbox Code Playgroud)
这是有趣的地方.我仍然在表达式中得到错误,left != right调试器在那里停止,但是第一个ATLTRACE被跳过了,或者第二个已经提前运行了!调试器输出有两行,count调试器显示的值与最后一行输出匹配.
Iterator comparison left _Getcont()=07D0B2C8 right _Getcont()=07D0B2C8 2984
left _Getcont()=07D0B2C8 right _Getcont()=07D0B2C8 2985
Myprog.exe has triggered a breakpoint.
Run Code Online (Sandbox Code Playgroud)
查看反汇编窗口会按预期顺序显示说明.我很难过.可能会发生什么?
Mar*_*som 12
终于想通了.Microsoft功能_Debug_message显示一个对话框,询问您是要中止,重试(调试)还是忽略错误.显示对话框时,消息泵仍在运行,允许进行其他活动.我的函数再次被调用,这次它运行完成,在这个过程中产生了大量的调试输出.如果我_DEBUG_ERROR在库代码中的行上放置一个显式断点,我会在后台没有额外执行的情况下捕获错误.回顾一下调试输出,事后看来我可以看到预期的错误输出确实存在,只是埋没到目前为止我从未见过它.
我的直觉告诉我,奥卡姆剃刀是最有可能的解释:具体来说,您在迭代期间使迭代器无效。事实上,您没有++iterfor 循环,这进一步强调了它不是对每个元素的直接迭代。
它可能不是直接在循环内部,但容器可能在从循环体调用的调用链中的某个地方使用别名 - 这些都是很容易犯的错误,并且诊断起来绝对残酷。您至少应该在每次迭代时打印容器的大小。
如果您可以访问 Linux 并使用足够小的代码来重现该问题,您也可以利用 valgrind 来帮助您解决这个问题。
| 归档时间: |
|
| 查看次数: |
644 次 |
| 最近记录: |