GObject   オブジェクト

ホーム   C/C++チュートリアル  

オブジェクト - クラスとインスタンス

GObject では GObject というクラスが基底クラスになります。つまり GObject クラスはクラス継承関係の頂点にあり、 GObject の上にスーパークラスはありません。

GObject クラスは GObject のインスタンスを作るときに自動的に作られます。

GObject クラスは一つしか作られません。その後に GObject のインスタンスをいくつ作っても、 GObject クラスが増えることはありません。

ソースコード

次のコードを object.c という名前で記述して保存してください。

object.c


#include <glib-object.h>

int
main (int argc, char **argv)
{
  GObject *ins1, *ins2;
  GObjectClass *cls1, *cls2;
  
  ins1 = g_object_new (G_TYPE_OBJECT, NULL);
  ins2 = g_object_new (G_TYPE_OBJECT, NULL);
  g_print ("ins1 address: %p\n", ins1);
  g_print ("ins2 address: %p\n", ins2);
  
  cls1 = G_OBJECT_GET_CLASS (ins1);
  cls2 = G_OBJECT_GET_CLASS (ins2);
  g_print ("cls1 adress: %p\n", cls1);
  g_print ("cls2 adress: %p\n", cls2);
  
  g_object_unref (ins1);
  g_object_unref (ins2);
  
  return 0;
}

ビルドと実行


// ビルド
cc object.c -o object `pkg-config --cflags --libs gtk4`

// 実行
./object

// 結果
ins1 address: 0x600001623be0
ins2 address: 0x600001623c00
cls1 adress: 0x600002421b90
cls2 adress: 0x600002421b90

// アドレスは実行時によって変わります。

インスタンス 1 と 2 のアドレスは違うので別のものだとわかります。
クラス 1 と 2 は同じアドレスなので、一つしかないことがわかります。

g_object_unref () で引数で指定したインスタンスが実際に格納されているメモリー部分が解放されます。
インスタンスのポインターである ins1 と ins 2 は main 関数が終わる時に自動的に解放されます。

なお、GObject のクラスは最後までメモリーに残り、プログラマが開放 (破棄) することはできません。
おそらく GObject のクラスはプログラムが終了するときに開放 (破棄) されるのだろうと思われます。

リファレンスカウント (Reference Count)

インスタンスは複数の箇所から参照される場合があります。どこかから参照されている時に g_object_unref で インスタンスを終了すると (メモリーを開放すると) エラーが起こる場合があります。そこで、GObject ではリファレンスカウント というシステムを使って、インスタンスの参照数を監督しています。

インスタンスが作成される時にインスタンスのリファレンスカウントは 1 になります。その後は、g_object_ref 関数を呼び出すたびに リファレンスカウントが一つずつ増えます。ある場所でインスタンスが不要になれば g_object_unref 関数を呼び出します。g_object_unref 関数は呼び出されるたびにリファレンスカウントを一つ減らします。 そしてリファレンスカウントが 0 になった時に、そのインスタンスの実体が入っているメモリーの部分が開放 (破棄)されます。

ref.c


#include <glib-object.h>

static void
count (GObject *ins)
{
  if (G_IS_OBJECT (ins))
  {
    g_print ("count: %d\n", ins->ref_count);
  }
  else
  {
    g_print ("ins is not GObject.\n");
  }
}

int
main (int argc, char **argv)
{
  GObject *ins = g_object_new (G_TYPE_OBJECT, NULL);
  g_print ("Object created.\n");
  count (ins);
  g_object_ref (ins);
  g_print ("Object was referenced.\n");
  count (ins);
  g_object_unref (ins);
  g_print ("Unref called.\n");
  count (ins);
  g_object_unref (ins);
  g_print ("Unref called.\n");
  //g_object_unref (ins);
  g_print ("Bye.\n");

  return 0;
}

ビルドと実行


// ビルド
cc ref.c -o ref `pkg-config --cflags --libs gtk4`

// 実行
./ref

// 結果

Object created.
count: 1
Object was referenced.
count: 2
Unref called.
count: 1
Unref called.
Bye.

// コメントアウトしている 3 番目の g_objet_unref(ins);のコメントを外してビルドと実行をすると
// 次のようなエラーが出てプログラムは途中で終了します。

zsh: segmentation fault  ./ref
zsh: セグメンテーション違反 ./ref

// Debian や Fedora などでは、Failed (失敗) とは表示されますが、
// 最後までプログラムは走って「Bye.」と表示されてから終了するみたいです。


46 visits
Posted: Mar. 22, 2025
Update: Mar. 24, 2025

ホーム   C/C++チュートリアル   目次