3

理解できないセグメンテーション違反が発生しています。私はWtライブラリを使用していて、シグナルを使っていくつかの凝ったことをしています(これは、これをデバッグしようとすることができたためにのみ言及します)。

ベクトルからウィジェットの1つへのポインターを取得し、それが指すオブジェクトのメソッドを呼び出そうとしています。Gdbは、ポインターが解決されることを示しています。ポインターが指すオブジェクトを調べると、まさにそれを変更する必要があります。この場合、ウィジェットはそれ自体にブロードキャストしているため、ブロードキャスターとリスナーの両方として登録されます。したがって、「broadcaster」ポインターと「listener」ポインターが同じオブジェクトにアクセスしていることも確認できました。彼らはそうします!

ただし、オブジェクトが存在し、初期化されており、実際には正しいオブジェクトであることがわかりますが、オブジェクトのメソッドを呼び出そうとすると、すぐにセグメンテーション違反が発生します。私はいくつかの異なるメソッドを試しました(オブジェクトを変更しないいくつかのブール値の戻り値を含む)。デバッグを試みるために、ブロードキャスターポインターとリスナーポインターを介してそれらを呼び出してみました。

デバッガーはオブジェクトを入力しません。セグメンテーション違反は、メソッドを呼び出そうとするとすぐに発生します。

コード!

/* listeners is a vector of pointers to widgets to whom the broadcasting widget
 * is trying to signal.
 */
unsigned int num_listeners = listeners.size();
for (int w = 0; w < num_listeners; w++)
{
    // Moldable is an abstraction of another widget type
    Moldable* widget = listeners.at(w);

    /* Because in this case, the broadcaster and the listener are one in the same, 
     * these two point to the same location in memory; this part works. I know, therefore,
     * that the object has been instantiated, exists, and is happy, or we wouldn't
     * have gotten to this point to begin with. I can also examine the fields with gdb
     * and can verify that all of this is correct.
     */
    Moldable* broadcaster_debug = broadcast->getBroadcaster();

    /* setStyle is a method I created, and have tested in other instances and it
     * works just fine; I've also used native Wt methods for testing this problem and
     * they are also met with segfaults. 
     */
    widget->setStyle(new_style); // segfault goes here!
}

ポインタをベクトルに格納することは最善のアイデアではないことを調査して以来読んだので、boost::shared_ptrを調べる必要があります。それはそうかもしれません、そして私はそれを調べます、しかしそれは存在することが知られているオブジェクトでメソッドを呼び出すことがなぜセグメンテーション違反を引き起こすのか説明しません。なぜこれが起こっているのか理解したいのですが。

助けてくれてありがとう。

編集:投稿に快適に収まるよりも多くのコードであったため、ベクトル操作の詳細を含む要点を作成しました。 https://gist.github.com/3111137

再帰的アルゴリズムであるため、ウィジェットが作成されるコードは示していません。そのためには、ウィジェットを作成するためのクラス決定木全体を表示する必要があります。ウィジェットが作成されていると言えば十分です。ブラウザでアプリケーションを表示すると、ページに表示されます。派手な信号で遊び始めるまで、すべてが正常に機能します。

Moar Edit:命令ステッピングモードでの逆アセンブルを見ると、セグメンテーション違反が発生する直前に次の操作が行われ、最初の引数が「void」としてリストされていることがわかります。確かに、私は残念ながら議会について何も知りませんが、これは重要なようです。この指示が何を意味するのか、そしてそれが私の苦痛の原因である可能性があるかどうかを誰かが説明できますか?

 add $0x378,%rax //$0x378 is listed as 'void'

別の編集:誰かの提案で、セグメンテーション違反の直前に正常に呼び出すことができる非仮想メソッドを作成しました。これは、オブジェクトが実際にそこにあることを意味します。同じ方法で仮想化すると、セグメンテーション違反が発生します。では、なぜ仮想メソッドだけがセグメンテーション違反を引き起こすのでしょうか?

呼び出し元のクラスで、Moldable :: debug_test(およびMoldable :: setStyle)を必ず指定すると、セグメンテーション違反が発生しないことがわかりました。ただし、これはconstバブリングと同様の効果があるようです。すべての仮想メソッドは、この指定子を必要としているようです。私はこれまでこの行動を目撃したことがありません。それが本当に想定されている方法である場合、私は自分のコードを修正するつもりですが、根本的な問題が他のものであるかどうかはわかりません。

そこに着く!

4

1 に答える 1

0

まあ、私は問題を理解しましたが、プロジェクトの性質上、見つけるのが非常に困難だったのはまったく初歩的な間違いだったと言って悲しいです. ここに答えを入れます。また、ローカライズされすぎているため、質問を閉じることに投票しました。お気軽にどうぞ。

BroadcastMessageクラスには__broadcasterフィールド ( Moldable* __broadcaster;)がありました。ブロードキャスターへのポインターをBroadcastMessageコンストラクターに渡すときに、インバウンド ポインターをそのフィールドに割り当てるのを忘れていました。つまり、__broadcaster はMoldableクラスの完全に実現されたインスタンスではありませんでした。

したがって、いくつかのメソッドは実際に機能していました-インライン化できるメソッド、またはテスト用に作成したダミー関数(たとえば、そのうちの1つは値1を返しました)、そこに完全なオブジェクトがあるように見えました実際にはありませんでした。セグメンテーション違反が発生したのは、オブジェクトの特定の動的プロパティにアクセスしようとする、より特殊なメソッドを呼び出すまでではありませんでした。

さらに、ブロードキャスト メッセージの寿命のほとんどはそのコンストラクター内にありました。つまり、ブロードキャスターはコンストラクターのローカル スコープで使用できるため、その目的のほとんどは問題なく達成されました。

ただし、提案どおりに Valgrind を使用すると、他の潜在的な問題がいくつか明らかになりました。また、プロジェクト全体をかなり削ぎ落として再構築しました。大量の不要なコードを破棄した結果、実行速度が大幅に向上しました。

とにかく、すべての支援に感謝します。申し訳ありませんが、解決策は発見ではありませんでした。

于 2012-07-18T11:33:06.457 に答える