7

Gtkmmの人たちは以下と比較 Glib::RefPtrしていstd::auto_ptr<>ます:

Glib::RefPtrスマートポインタです。具体的には、参照カウントのスマートポインタです。std::auto_ptr<>あなたは、スマートポインターでもあるが、Glib::RefPtr<>はるかに単純で、より便利な、に精通しているかもしれません。

しかし、奇妙な理由で、私は自分の仕事を終わらせることができませんRefPtr。同じコードは。で問題ありませんauto_ptr

次のコードでSmartPtrは、はこれら2つのスマートポインターのいずれかのプレースホルダーにすぎません。

#include <gtkmm.h>
#include <iostream>
#include <tr1/memory>

struct WindowHolder {
  SmartPtr<Gtk::Window> ptr;

  WindowHolder()
    : ptr(new Gtk::Window)
  {
    ptr->signal_delete_event().connect(sigc::mem_fun(*this, &WindowHolder::reset));
    ptr->show_all();
  }

  bool reset(GdkEventAny* event)
  {
    Gtk::Main::quit();
  }
};

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);
  WindowHolder w;
  kit.run();
}

コンパイルするとき、私は最初にとして定義SmartPtrGlib::RefPtr、次にとして定義しますstd::auto_ptr

$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-3.0` main.cc && ./a.out 
(main:22093): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed
$ g++ '-DSmartPtr=std::auto_ptr' `pkg-config --cflags --libs gtkmm-3.0` main.cc && ./a.out 
$

問題はこれGLib-GObject-CRITICALです。私の実際のアプリケーションでは、これは1行だけでなく、多数の行です。2番目のバージョンでは、std::auto_ptrすべてがうまく破壊されます。

奇妙なことに、GTK2では問題ないコードです。

$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-2.4` main.cc && ./a.out 
$

非推奨であるため、依存したくstd::auto_ptrありません。また、デストラクタがポインタを手動で削除する必要があるため、生のポインタを操作したくないため、複雑さが増します...

私の質問は次のとおりです。

  1. なぜGlib::RefPtrこの「重大な警告」(おそらくダブルフリー)が発生するのですか?
  2. なぜgtkmm2.4では動作するのに3.0では動作しないのですか?
  3. Glib::RefPtrとgtkmm3.0でコードを修正できますか?
  4. このような状況を一般的にどのように処理する必要がありますか?
4

2 に答える 2

5

Glib::RefPtr は、一般的な使用を意図したものではありません。API が強制する場合は使用する必要がありますが、それ以外の場合は使用しないでください。GtkWindow (または Gtk::Window) には独自の奇妙なメモリ管理があり、RefPtr と実際には互換性がありません。

汎用のスマートポインターが必要な場合は、std::shared_ptr または std::unique_ptr を試してください。または、ブーストで何かを見つけることができます。

于 2012-04-17T20:14:17.093 に答える
4

参照カウントが低すぎるため、ptr->reference()afterを追加することで修正できますptr->show_all()。説明がありますが、一粒の塩でそれを取ってください:

  • Glib::RefPtr は、最初はそのオブジェクトの参照カウントをインクリメントしません。
  • GtkWindow の参照カウントは、最初は 1 です。
  • ウィンドウが閉じられると、ライブラリは GtkWindow の参照カウントを 1 回減らします。
  • GtkWindow のカウントはゼロなので、破棄されます。
  • kit.run() は、これ以上ウィンドウがないことを確認し、戻ります。
  • w が範囲外になり、RefPtr のオブジェクトのカウントが減少してエラーが発生します。

gtk/gtkmm のこの領域は (私にとって) まだ少し不可解なため、残念ながら #2 または #4 に答えることができません。

参照: http://www.gtkforums.com/viewtopic.php?t=2412

于 2012-04-14T23:43:44.520 に答える