13

forループ内の不思議な反復子の問題を追跡しようとしています。イテレーターでエラーが発生しますoperator!=。これは通常、比較されるイテレーターが同じコンテナーに属していないことを意味します。ライブラリの Microsoft の実装をトレースすると、このテストが true の場合に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");

!=より多くの情報を取得するために、forループ内のmy を置き換えるために、この小さな関数を作成しました。

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;
}

ここが興味深いところです。式でまだエラーが発生しleft != right、デバッガーはそこで停止しますが、最初の式ATLTRACEがスキップされたか、2 番目の式が事前に実行されました! デバッガーの出力には両方の行がありcount、デバッガーによって表示される as の値は、出力の最後の行と一致します。

Iterator comparison left _Getcont()=07D0B2C8 right _Getcont()=07D0B2C8 2984
                    left _Getcont()=07D0B2C8 right _Getcont()=07D0B2C8 2985
Myprog.exe has triggered a breakpoint.

逆アセンブリ ウィンドウを見ると、予想される順序で命令が表示されます。私は困惑しています。何が起こっているのでしょうか?

4

2 に答える 2

12

最後にそれを理解しました。Microsoft 関数_Debug_messageは、エラーを中止するか、再試行 (デバッグ) するか、または無視するかを尋ねるダイアログ ボックスを表示します。ダイアログ ボックスが表示されている間、メッセージ ポンプはまだ実行されているため、他のアクティビティを実行できます。私の関数が再び呼び出され、今度は完了するまで実行され、その過程で多くのデバッグ出力が生成されました。ライブラリコードの行に明示的なブレークポイントを配置する_DEBUG_ERRORと、バックグラウンドで追加の実行なしでエラーをキャッチします。後知恵でデバッグ出力を振り返ると、予期されたエラー出力が確かにそこにあったことがわかります。

于 2013-06-10T16:47:40.380 に答える
3

私の直感では、オッカムのかみそりがここで最も可能性の高い説明であることがわかります。具体的には、反復中に反復子を無効にしていることです。for ループに a がないという事実は、++iterすべての要素に対する単純な反復ではないことをさらに強調しています。

おそらくループ内に直接存在するわけではありませんが、ループ本体から呼び出される呼び出しチェーン内のどこかでコンテナーがエイリアス化されている可能性があります。これらは非常に簡単な間違いであり、診断するのは非常に困難です。少なくとも、反復ごとにコンテナーのサイズを出力する必要があります。

Linux にアクセスでき、問題を再現するコードのごく一部しかない場合は、valgrind を利用して問題を突き止めることもできます。

于 2013-06-10T16:24:29.890 に答える