前の月 / 次の月 / 最新

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

2009-01-23 Fri

デストラクタの中で呼び出し元を判別 [D言語]

たまたま、 BlkAttr.FINALIZE のクリアのタイミングが違うから、
dmd 2.023 で出来たけど…

class C
{
    ~this()
    {
        writefln(GC.getAttr(cast(void*)this)&GC.BlkAttr.FINALIZE);
    }
}

void main()
{
    C c1 = new C;
    delete c1;

    {
        scope C c2 = new C;
    }

    C c3 = new C;
    writefln("---");
}
1
0
---
0

delete で呼び出されたデストラクタ中では、 BlkAttr.FINALIZE が立っている。
GC で呼び出されたデストラクタ中では、 BlkAttr.FINALIZE が立っていない。

デストラクタの中で呼び出し元が判別できる。
よって次のコードが書ける。

class C
{
    ~this()
    {
        if(GC.getAttr(cast(void*)this)&GC.BlkAttr.FINALIZE)
        {
            writefln("Clean up all managed resources");
        }
        writefln("Clean up all native resources");
    }
}

scope 変数の場合 GC から呼ばれた場合と同じく BlkAttr.FINALIZE を消してから、
デストラクタが呼ばれる。

2009-01-22 Thu

nothrow関数 [D言語]

nothrow関数

nothrow関数は、
クラス Exception から派生した例外を一切投げない関数です。

nothrow で宣言された関数は、
nothrow で宣言された関数以外を呼び出すとエラー。

それ以外にも、次の文が含まれるとエラーが出る。
new 文 OutOfMemoryException が投げられる可能性がある。
switch 文 SwitchErrorn が投げられる可能性がある。

2009-01-10 Sat

ひどい

S101 の初期セットアップに失敗する。

「致命的なエラー :レジストリを更新できなかったため…」

もしかして、イメージが壊れているのか?

パソコンを使う前から再インストールなんて初めてだ。

IDisposableをDで [D言語]

CLR 徹底解剖: IDisposable について
GC.SuppressFinalize の代わりに、
GC.clrAttr を使って、FINALIZE を消せば、
IDisposable をDで書けそうだ。

結局、リソースは自分で明示的に解放しなくてはいけない。

2009-01-09 Fri

リソース管理 [D言語]

デストラクタ

GC が参照されなくなったオブジェクトを必ず解放するという保証はありません。
さらに、
GC がデストラクタを呼び出す順番も保証されません。
これはつまり、
GC管理下にあるオブジェクトへの参照をメンバとして持つオブジェクトのデストラクタを
ガベージコレクタが呼び出すときには、それらの参照は既に無効となっている可能性があるということです。
従って、
デストラクタからはメンバオブジェクトを参照できません。
この規則は、
autoオブジェクトや DeleteExpression
で削除されるオブジェクト
(GCが自動で解放することはないので、参照は必ず有効)には当てはまりません。

GC でデストラクタが呼ばれる保証がない。
GC でデストラクタが呼ばれるのを、期待して、デストラクタにリソースの解放を書くと、
リソースリークする。

class ComString{...}
void main()
{
    ComString s = new ComString("foo"); //GC がデストラクタを呼ばないかもしれない。
}

GC で呼ばれるデストラクタからメンバオブジェクトを触れないので
scope属性や、delete式でデストラクタが実行されるようにしなければならない。

delete式では、忘れる可能性がある。

class ComString{...}
void main()
{
    ComString s = new ComString("foo"); //delete式を書き忘れた
}

scope変数を使いRAIIにしたい。
scope変数を使うように強制するためにscopeクラスする。

scope class ComString{...}
void main()
{
    scope ComString s = new ComString("foo"); //デストラクタが動く
}

scopeクラスにすると、
メンバオブジェクトにできない。

scope class ComString{...}
class MyString
{
    scope ComString s;//コンパイルエラー
    ComString s;//コンパイルエラー
}

過去ログ

2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12