1

編集:問題は解決しました。これは (また別の) 状況で、実際には問題があるように見える場所ではありませんでした。手がかりは、@0xfeeefefe をオブジェクトへのポインターとして使用することでした。これは、メモリを解放するときに Windows API 関数によって返されるアドレスです...操作されていたオブジェクトが削除されたことを示します。

std::map から値を消去しようとしているときにセグメンテーション違反が発生しましたが、その理由を一生理解できません。デバッガー (gdb) から次のように表示されます。

Program received signal SIGSEGV, Segmentation fault.
0x0048785f in std::less<irr::gui::IGUIWindow*>::operator()(irr::gui::IGUIWindow* const&, irr::gui::IGUIWindow* const&) const (this=0x258ab04, __x=@0x22f778, __y=@0xfeeefefe)
at C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_function.h:227
227           { return __x < __y; }

しかし、奇妙な部分は、これら 2 つの入力値の次の検査です。

(gdb) x 0x22f778
0x22f778:       0x025e1ef8
(gdb) x 0xfeeefefe
0xfeeefefe:     0x025e1ef8

背景: マップは、ポインターからポインターへのマッピングです。具体的には、キーは gui システムのウィンドウへのポインターであり、値はそのウィンドウに出力される情報を送信できるオブジェクトへのポインターです。デバッグ可能オブジェクトからウィンドウへの逆マップもあります。その理由は、ウィンドウが閉じている場合、デバッグ可能なオブジェクトに通知する必要があるためです。これにより、データを送信しようとして時間を無駄にすることができなくなります。逆マッピングは、マネージャー (このコードが含まれるクラス) がデバッグ可能なオブジェクトからパケットを受信したときに、どのウィンドウに情報を出力するかを認識できるようにするためのものです。

問題は、なぜ 2 つのポインター値を比較するとreturn( 0x025e1ef8 < 0x025e1ef8 )エラーが発生するのかということです。

私は自分のコードのある時点でのみ消去しようとしますが、それはループではないため、破損する反復子はありません。また、そのマップの別の場所に物を挿入するだけで、物が挿入されたり消去されたりするときにトレースが印刷されますが、それには何の問題もありません。

これが実際に役立つ情報ではないことはわかっていますが、コードが非常に大きく、問題を追跡するために何ができるかわかりません。提案があれば、さらに情報を提供したいと思います。何が起こっているのかを簡単に理解できるように、コードの一部を貼り付けます。私の問題が何であるかを示す何かがここにあることを願っています。

ここが問題の部分です

case EGET_ELEMENT_CLOSED:
{
    IGUIWindow* window =
        static_cast<IGUIWindow*>(event.GUIEvent.Caller);

    if( m_debugMap.find(window) != m_debugMap.end())
    {
        IGuiDebuggable* debug = m_debugMap[window];
        debug->removeListener(this);

        cout << "closing window: " << window << " attached"
                " to debuggable: " << debug << endl;

        m_debugMap.erase(window);    /// segfault here
        m_conMap.erase(debug);       /// if above line commented, segfault here
    }

    m_eventMap.erase(window);    /// if above block commented, segfault here
    window->remove();
    return true;
}

そして、これが要素がマップに追加される部分です

IGUIElement*    winElmnt    =
                    m_env->getRootGUIElement()->getElementFromId(0,false);

IGUIElement*    editElmnt   = winElmnt->getElementFromId(1);
IGUIWindow*     window      = static_cast<IGUIWindow*>(winElmnt);

cout << "CModelTesterGui: adding " << window << "(" << winElmnt
     << ") to the debug map with edit box " << editElmnt << endl;

m_conMap[debug]             = static_cast<IGUIEditBox*>(editElmnt);
m_debugMap[window]          = debug;

window->setID(-1);
debug->addListener( this );

ご覧のとおり、何が起こっているのか、何がマップから消去されようとしているのかのアドレスを出力しています。それらは期待どおりに対応しているため、機能していない値などを消去しようとしているわけではありません。

あ、あと最後に一言。ここに奇妙な癖があります。ウィンドウを 1 つだけ開いた場合 (マップに要素を 1 つだけ追加した場合) は、問題なく消去できます。2 つ以上の要素をマップに追加した後でのみ、そのうちの 1 つを消去しようとするとセグメンテーション違反が発生します。

4

3 に答える 3

2

あ、あと最後に一言。ここに奇妙な癖があります。ウィンドウを 1 つだけ開いた場合 (マップに要素を 1 つだけ追加した場合) は、問題なく消去できます。2 つ以上の要素をマップに追加した後でのみ、そのうちの 1 つを消去しようとするとセグメンテーション違反が発生します。

奇妙な癖は通常、メモリの問題を表します。valgrind を実行してみましたか?

クローンを挿入していますか?ポインターは、マップへの挿入と削除の間のどこかで削除されていますか?

于 2009-08-19T02:24:32.367 に答える
2

0xfeeefefe実際の比較の前に、を逆参照しようとして segfault が発生したようです。

FEEEFEEE 解放されたヒープ メモリをマークするために Microsoft の HeapFree() によって使用されます(1)

__x との型は何__yですか? __xとに書き込まれた初期値を確認してから__y、変更がないかメモリ位置を監視できますか?

また、HeapFree関数にブレーク ポイントを設定できれば、不正なメモリ参照をキャッチできる可能性があります。

于 2009-08-19T02:40:15.820 に答える
1

私はあなたのトレースバックを見ていて

、__x=@0x22f778, __y=@0xfeeefefe と書かれているところを見ています。これは、__

x と __y が参照であることを示唆しているようです。

その場合、( __x < __y ) をテストしようとすると、それらを逆参照している可能性があり、マシンに beaucoup メモリがインストールされていない限り、0xfeeefefe を逆参照することはあまり良いことではない可能性があります。

于 2009-08-19T03:07:50.333 に答える