読者です 読者をやめる 読者になる 読者になる

C++0x ガベージコレクションと到達可能性ベースリーク検知の最小支援

C++

結論からいうと、 C++0x に GC は入りません。
C++0x では、透過的な GC の導入が間に合わないので、最低限の決めごとだけを行います。


で、以下が C++0x での GC の決めごと


【目的】
GC と到達可能性ベースリーク検知の両方のサポート



【背景】
以下のような"hide a pointer"(ポインタを隠す)プログラム(ポインタを他の値とXORして、あとでそれを通常のポインタに戻して参照をはずす)は未定義動作となります。

T *p = new ...;
intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555;
    // ここでGCが起こったら・・・
T *q = reinterpret_cast<T*>(x ^ 0x555);
T y = *q;

・hide a pointer のみで参照されるオブジェクトは、GCによって早く回収されてしまうかもしれないという問題を作り出す
・同じ理由で、到達可能性ベースリーク検知は、そのようなプログラムリークメモリの謝った報告をする可能性がある。
・quick_exit() 機能を利用するプログラムにとっては、到達可能性ベースリーク検知は、リーク検知のおそらく唯一見込みのある形式となる。



【言語仕様での対応】

Safely-derived Pointer という考え方を導入する。

  • トレース可能なポインタオブジェクトとは
    • オブジェクトへのポインタ型のオブジェクトか、
    • 少なくとも std::intptr_t と同じだけの大きさをもつ整数型か、
    • あるオブジェクトへのポインタ型とその並びのサイズやアライメントが一致する文字型の配列の中の要素の並び
  • ポインタ値が動的オブジェクトへの Safely-derived Pointer となりうる場合とはオブジェクトへのポインタ型であり、かつ以下の条件のとき
    • C++標準ライブラリの ::operator new(std::size_t) の呼び出しによって返却される値
    • 参照外しする Safely-derived Pointer 値によって返却される左辺値のサブオブジェクトのアドレスのとる結果
    • Safely-derived Pointer 値を利用する明確なポインタ計算の結果
    • Safely-derived Pointer 値の reinterpret_cast の結果
    • Safely-derived Pointer 値の整数表現の reinterpret_cast の結果
    • コピー時にそのソースオブジェクトが Safely-derived Pointer 値のコピーを含んでいるような場合、追跡可能ポインタオブジェクトからコピーされたオブジェクトの値
  • もし、 Safely-derived Pointer 値でないポインタが参照外し、または解放されてしまい、かつその参照されていた総体オブジェクト(complete object)が動的ストレージ内であり、到達可能と宣言されていなかった場合、その動作は未定義である。

【ライブラリでの対応】

  • ユーザー提供のポインタ値や intptr_t 型の変数をもつ、標準ライブラリによって構築されたオブジェクト、トレース可能ポインタ位置に格納されてなくてはならない。
void declare_reachable(void* p)

p が NULL でなければ、 p によって参照される総体オブジェクトは、その後到達可能と宣言される。

template <typename T>
T* undeclare_reachable(T* p)

p の safety-derived のコピーを返す。

void declare_no_pointers(char* p, size_t n)

p から始まる n バイトは、もはやトレース可能ポインタ位置に含まれない。

void undeclare_no_pointers(char* p, size_t n)

declare_no_pointers に登録された範囲を無効にする。
オブジェクトの寿命が終わるまえに呼び出されなくてはならない。

namespace std {
    enum class pointer_safety {
        relaxed, preferred, strict
    };
}

pointer_safety get_pointer_safety()

safely-derived でないポインタの処理系の扱いを示す列挙値を返す。

  • relaxed : safely-derived でないポインタがそのプログラムの有効期間に safely-derived であるポインタと同様に扱われる
  • preferred : safely-derived でないポインタがそのプログラムの有効期間に safely-derived であるポインタと同様に扱う、ただし、 safely-derived でない参照外しされるポインタを取り除くことを求めるヒントを実装することを許可する
  • strict : safely-derived でないポインタを safely-derived であるポインタとは異なるものとして扱う

N2670 Minimal Support for Garbage Collection and Reachability-Based Leak Detection (revised)


より全般的な議論と、透過的なガベージコレクションをサポートする理由については、N2585N2310を参照してください。


C++0x言語拡張まとめ