ホーム > Lua > Luaのdestructor(デストラクタ)とGC

Luaのdestructor(デストラクタ)とGC

2009 年 6 月 2 日

LuaにはGCが付いていますので、使われなくなったメモリは回収されます。

強制的に呼び出すのは簡単で、回収したいところで

collectgarbage(“collect”)

とするだけです。

C++ではクラスインスタンスの解放時にデストラクタが呼ばれます。

自前のリソースの解放には便利です。

さっそく、Luaの自作クラスでやってみます。

何やらメタテーブルに__gcメソッドを書けばよろしいようで、簡単簡単。

function destruct()
        print("destructor called")
end

t = {}
setmetatable(t, {__gc = destruct})

t = nil
collectgarbage("collect")
print("end")

実行してみたものの、endしか表示されず、destruct関数が呼ばれない・・・

仕様を見てみると、ユーザデータ(テーブルではない)のメタテーブルに対して

__gcメソッドを定義しないといけない模様・・・

ユーザデータを作ってくれるnewproxy関数を発見!

この関数は非公開メソッドのようです。

この関数の引数がtrueなら、新しいメタテーブルを内包するユーザデータを作ります。

引数が既に作成してあるユーザデータなら、そのユーザデータに含まれるメタテーブルをコピーします。

先ほどのプログラムを次のように変更します。

function destruct()
        print("destructor called")
end

t = {_udata = newproxy(true) }
setmetatable(t._udata, {__gc = destruct})
t = nil
collectgarbage("collect")
print("end")

うまくいくだろうと思いきや、Luaが怒りました。

bad argument #1 to ‘setmetatable’ (table expected, got userdata)

つまり、setmetatable関数にはテーブルしか指定できないようです。

また調べると、getmetatable関数はユーザデータでも構わないとののこと。

もう一度プログラムを書き換えてみました。

function destruct()
        print("destructor called")
end

t = {_udata = newproxy(true) }
getmetatable(t._udata).__gc = destruct
t = nil
collectgarbage("collect")
print("end")

実行してみると・・・無事デストラクタが呼び出されました。

destructor called
end

admin Lua

コメントは受け付けていません。