狠狠撸

狠狠撸Share a Scribd company logo
GC in C++0x

  2010/8/8 GC本読書会

  新 康孝
  yak_ex
自己紹介
? 氏名: 新 康孝 (あたらし やすたか)
? Twitter ID: yak_ex
? Web: http://yak3.myhome.cx:8080/junks

? C++ / Perl が主戦場
? 某自動車部品メーカーから某自動車メーカーへ出向中
? 現在、仕事でコードに触れていない
? 競技プログラミング(TopCoder、Codeforces)で
  潤い補充
? GC は「ど素人」
渡る世間は GC ばかり
? Google Code Jam 2010 Qualifier 使用言語
 1位   C++    4911 6位    Ruby      221
 2位   Java   2762 7位    PHP       170
 3位   Python 1459 8位    Perl      146
 4位   C       751 9位    Haskell   118
 5位   C#      648 10位   Pascal     95
渡る世間は GC ばかり
? Google Code Jam 2010 Qualifier 使用言語
 1位   C++    4911 6位    Ruby      221
 2位   Java   2762 7位    PHP       170
 3位   Python 1459 8位    Perl      146
 4位   C       751 9位    Haskell   118
 5位   C#      648 10位   Pascal     95

? 黄色ハイライト=GC有り言語
渡る世間は GC ばかり
? Google Code Jam 2010 Qualifier 使用言語
 1位   C++    4911 6位    Ruby      221
 2位   Java   2762 7位    PHP       170
 3位   Python 1459 8位    Perl      146
 4位   C       751 9位    Haskell   118
 5位   C#      648 10位   Pascal     95

? 黄色ハイライト=GC有り言語
? 超一線級言語でありながら GC 無し : C++は孤高
C++は孤高
? そんな C++ を支える C++er 達
C++は孤高
? そんな C++ を支える C++er 達
     闇
C++は孤高
? そんな C++ を支える C++er 達
     闇

     の
C++は孤高
? そんな C++ を支える C++er 達
     闇

     の

     軍
C++は孤高
? そんな C++ を支える C++er 達
     闇

     の

     軍

     団
C++は孤高
? そんな C++ を支える C++er 達
     闇へ

     の   ん
     軍た

     団い
マルチパラダイム変態言語C++
? 次期標準規格 C++ 0x では

          Support for
       Garbage Collection
             and
Reachability-Based Leak Detection
マルチパラダイム変態言語C++
? 次期標準規格 C++ 0x では

  Minimal Support for
       Garbage Collection
             and
Reachability-Based Leak Detection
Minimal Support for GC 以下略
? いくつかの概念
 ? Traceable pointer object
 ? Safely-derived pointer (value)
? 5つの関数
 ? get_pointer_safety()
 ? (un)declare_no_pointers()
 ? (un)declare_reachable()
いくつかの概念(1)
? Traceable pointer object
  ? ポインタobj
  ? ポインタを格納するのに十分なサイズの整数obj
  ? キャラクタ型の配列の一部分
    キャラクタ型だけな理由は恐らく strict aliasing rule
  →ポインタ値が入っているかもしれないと処理系に
   認識してもらえるobject
  =他の部分にはポインタ値が入っていない前提
いくつかの概念(2)
? Safely-derived pointer (value)
  ? ::operator new で返ってきた値 (例: new T)
  ? Safely-derived pointer value に対する
    ? 逆参照→参照の結果 (例: &*p)
    ? ポインタ値の well-defined な演算結果 (例: p+1)
    ? ポインタ間の well-defined な変換結果
       (例: static_cast<void*>(p))
    ? ポインタ?整数値間の reinterpret_cast による変換結果
       (例: reinterpret_cast<intptr_t>(p))
  →::operator new で確保された領域で
    かつ有効であることが
    処理系から確実に追跡可能なポインタ値
いくつかの概念(3)
? Safely-derived pointer (value)
                             これは safely-derived pointer value

  T *p = new T;
  intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555
  a:
  T *q = reinterpret_cast<T*>(x ^ 0x555);
  T y = *q;


                       こっちは safely-derived pointer value ではない

                    これも safely-derived pointer value ではない!
                    ※値としては p と同じだが、結果ではなくて過程で判断
Minimal Support for GC 以下略
? いくつかの概念
 ? Traceable pointer object
 ? Safely-derived pointer (value)
? 5つの関数
 ? get_pointer_safety()
 ? (un)declare_no_pointers()
 ? (un)declare_reachable()
関数: get_pointer_safety()
? 処理系のポインタ安全性(pointer safety)を
  返す
                Safely-derived pointer であるかによって
 ? relaxed:     処理が変わらない=C++03相当
                ※relaxed と preferred は処理系定義
 ? preferred:     preferred だと leak detector があったりする
                  かもしれない
                ※VC2010 は relaxed 返して他の関数も何もしない


 ? strict:      safely-derived pointer でないポインタ値
                (かつ後述の declare_reachable() が呼ばれてい
                ない値)を介して動的確保された領域を逆参照、解放
                すると未定義動作
Strict pointer safety
? Safely-derived pointer (value)
                             これは safely-derived pointer value

  T *p = new T;
  intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555
  a:
  T *q = reinterpret_cast<T*>(x ^ 0x555);
  T y = *q;


                       こっちは safely-derived pointer value ではない

                    これも safely-derived pointer value ではない!
   未定義動作
                    ※値としては p と同じだが、結果ではなくて過程で判断
関数: (un)declare_no_pointers()
? void declare_no_pointers(char *p,
  size_t n);
? void undeclare_no_pointers(char *p,
  size_t n);
? 指定された領域内にポインタ値がないことを
  指定 or 指定解除する
→GC のスキャン範囲を狭められる
関数: (un)declare_reachable
? void declare_reachable(void *p);
  ? safely-derived な pointer 値 p の参照先を
    reachable だと宣言する
  →参照先を GC 対象からはずす
? template<class T>
  T* undeclare_reachable(T *p);
  ? 参照先が reachable な p に対して、
    safely-derived な pointer 値(pと同じ値)を返す
  →参照先が GC 対象に復帰する
   (※返値が safely-derived なので有効である間はGCされ
    ない)
(耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方
? どうして必要なの?                   これは safely-derived pointer value

   T *p = new T;
   intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555
   a:
   T *q = reinterpret_cast<T*>(x ^ 0x555);
   T y = *q;

                        こっちは safely-derived pointer value ではない
    未定義動作            これも safely-derived pointer value ではない!
                     ※値としては p と同じだが、結果ではなくて過程で判断

「ラベル a: の位置で GC がかかると p の参照先が回収される」 ???
(耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方
? どうして必要なの?                   これは safely-derived pointer value

   T *p = new T;
   intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555
   a:
   T *q = reinterpret_cast<T*>(x ^ 0x555);
   T y = *q;

                        こっちは safely-derived pointer value ではない
    未定義動作            これも safely-derived pointer value ではない!
                     ※値としては p と同じだが、結果ではなくて過程で判断

「ラベル a: の位置で GC がかかると p の参照先が回収される」                 問題は最適化
(耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方
? どうして必要なの?
   T *p = new T;                                        以降 p の値は
   intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555   使われない
   a:
   T *q = reinterpret_cast<T*>(x ^ 0x555);
   T y = *q;

   ※ p, x, q を同じレジスタに割り当てることが可能                         以降 x の値は
   →ラベル a: の時点で p の値がどこにも存在しない                          使われない
   →p の参照先 = q の参照先が GC の回収対象になる!!
   →*q で未定義動作

「ラベル a: の位置で GC がかかると p の参照先が回収される」                 問題は最適化
(耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方
    ? C++0xでの正しいコード
*p は
reachable T *p = new T;
=         declare_reachable(p); // 偽装前に declare_reachable() を呼ぶ
GC対象外 intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555
          a:
          // T z = *reinterpret_cast<T*>(x ^ 0x555); // 合法
          // 偽装終了時に undeclare_reachable() を呼ぶ
          T *q = undeclare_reachable(reinterpret_cast<T*>(x ^ 0x555));
          T y = *q;
注
※ declare_reachable した値と同じであれば safely-derived でなくとも逆参照が可能
※ undeclare_reachable の引数は safely-derived でなくとも reachable であれば良い
※ declare_reachable については「ポインタ値を偽装する」点が問題
   a: で関数が別れている場合を考えれば最適化なしで議論は一緒
まとめ
? C++0x では最小限の GC サポートがある
  ? Safely-derived pointer という概念
    = GC されていない生きているポインタ値
  ? 5 つの関数が追加
? C++03相当でも規格合致(relaxed)
  ? しばらくそれ以上の実装はでなさそう?
? ポインタ値を偽装するコードは
  declare_reachable() / undeclare_reachable()
  を使って修正する必要がある
参考文献
? N2670: Minimal Support for Garbage
  Collection and Reachability-Based Leak
  Detection (revised)
  http://www.open-
  std.org/jtc1/sc22/wg21/docs/papers/2008/
  n2670.htm
? Garbage Collection in the Next C++
  Standard
  http://www.hpl.hp.com/techreports/2009/H
  PL-2009-360.pdf

More Related Content

GC in C++0x

  • 1. GC in C++0x 2010/8/8 GC本読書会 新 康孝 yak_ex
  • 2. 自己紹介 ? 氏名: 新 康孝 (あたらし やすたか) ? Twitter ID: yak_ex ? Web: http://yak3.myhome.cx:8080/junks ? C++ / Perl が主戦場 ? 某自動車部品メーカーから某自動車メーカーへ出向中 ? 現在、仕事でコードに触れていない ? 競技プログラミング(TopCoder、Codeforces)で 潤い補充 ? GC は「ど素人」
  • 3. 渡る世間は GC ばかり ? Google Code Jam 2010 Qualifier 使用言語 1位 C++ 4911 6位 Ruby 221 2位 Java 2762 7位 PHP 170 3位 Python 1459 8位 Perl 146 4位 C 751 9位 Haskell 118 5位 C# 648 10位 Pascal 95
  • 4. 渡る世間は GC ばかり ? Google Code Jam 2010 Qualifier 使用言語 1位 C++ 4911 6位 Ruby 221 2位 Java 2762 7位 PHP 170 3位 Python 1459 8位 Perl 146 4位 C 751 9位 Haskell 118 5位 C# 648 10位 Pascal 95 ? 黄色ハイライト=GC有り言語
  • 5. 渡る世間は GC ばかり ? Google Code Jam 2010 Qualifier 使用言語 1位 C++ 4911 6位 Ruby 221 2位 Java 2762 7位 PHP 170 3位 Python 1459 8位 Perl 146 4位 C 751 9位 Haskell 118 5位 C# 648 10位 Pascal 95 ? 黄色ハイライト=GC有り言語 ? 超一線級言語でありながら GC 無し : C++は孤高
  • 6. C++は孤高 ? そんな C++ を支える C++er 達
  • 7. C++は孤高 ? そんな C++ を支える C++er 達 闇
  • 8. C++は孤高 ? そんな C++ を支える C++er 達 闇 の
  • 9. C++は孤高 ? そんな C++ を支える C++er 達 闇 の 軍
  • 10. C++は孤高 ? そんな C++ を支える C++er 達 闇 の 軍 団
  • 11. C++は孤高 ? そんな C++ を支える C++er 達 闇へ の ん 軍た 団い
  • 12. マルチパラダイム変態言語C++ ? 次期標準規格 C++ 0x では Support for Garbage Collection and Reachability-Based Leak Detection
  • 13. マルチパラダイム変態言語C++ ? 次期標準規格 C++ 0x では Minimal Support for Garbage Collection and Reachability-Based Leak Detection
  • 14. Minimal Support for GC 以下略 ? いくつかの概念 ? Traceable pointer object ? Safely-derived pointer (value) ? 5つの関数 ? get_pointer_safety() ? (un)declare_no_pointers() ? (un)declare_reachable()
  • 15. いくつかの概念(1) ? Traceable pointer object ? ポインタobj ? ポインタを格納するのに十分なサイズの整数obj ? キャラクタ型の配列の一部分 キャラクタ型だけな理由は恐らく strict aliasing rule →ポインタ値が入っているかもしれないと処理系に 認識してもらえるobject =他の部分にはポインタ値が入っていない前提
  • 16. いくつかの概念(2) ? Safely-derived pointer (value) ? ::operator new で返ってきた値 (例: new T) ? Safely-derived pointer value に対する ? 逆参照→参照の結果 (例: &*p) ? ポインタ値の well-defined な演算結果 (例: p+1) ? ポインタ間の well-defined な変換結果 (例: static_cast<void*>(p)) ? ポインタ?整数値間の reinterpret_cast による変換結果 (例: reinterpret_cast<intptr_t>(p)) →::operator new で確保された領域で かつ有効であることが 処理系から確実に追跡可能なポインタ値
  • 17. いくつかの概念(3) ? Safely-derived pointer (value) これは safely-derived pointer value T *p = new T; intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555 a: T *q = reinterpret_cast<T*>(x ^ 0x555); T y = *q; こっちは safely-derived pointer value ではない これも safely-derived pointer value ではない! ※値としては p と同じだが、結果ではなくて過程で判断
  • 18. Minimal Support for GC 以下略 ? いくつかの概念 ? Traceable pointer object ? Safely-derived pointer (value) ? 5つの関数 ? get_pointer_safety() ? (un)declare_no_pointers() ? (un)declare_reachable()
  • 19. 関数: get_pointer_safety() ? 処理系のポインタ安全性(pointer safety)を 返す Safely-derived pointer であるかによって ? relaxed: 処理が変わらない=C++03相当 ※relaxed と preferred は処理系定義 ? preferred: preferred だと leak detector があったりする かもしれない ※VC2010 は relaxed 返して他の関数も何もしない ? strict: safely-derived pointer でないポインタ値 (かつ後述の declare_reachable() が呼ばれてい ない値)を介して動的確保された領域を逆参照、解放 すると未定義動作
  • 20. Strict pointer safety ? Safely-derived pointer (value) これは safely-derived pointer value T *p = new T; intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555 a: T *q = reinterpret_cast<T*>(x ^ 0x555); T y = *q; こっちは safely-derived pointer value ではない これも safely-derived pointer value ではない! 未定義動作 ※値としては p と同じだが、結果ではなくて過程で判断
  • 21. 関数: (un)declare_no_pointers() ? void declare_no_pointers(char *p, size_t n); ? void undeclare_no_pointers(char *p, size_t n); ? 指定された領域内にポインタ値がないことを 指定 or 指定解除する →GC のスキャン範囲を狭められる
  • 22. 関数: (un)declare_reachable ? void declare_reachable(void *p); ? safely-derived な pointer 値 p の参照先を reachable だと宣言する →参照先を GC 対象からはずす ? template<class T> T* undeclare_reachable(T *p); ? 参照先が reachable な p に対して、 safely-derived な pointer 値(pと同じ値)を返す →参照先が GC 対象に復帰する (※返値が safely-derived なので有効である間はGCされ ない)
  • 23. (耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方 ? どうして必要なの? これは safely-derived pointer value T *p = new T; intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555 a: T *q = reinterpret_cast<T*>(x ^ 0x555); T y = *q; こっちは safely-derived pointer value ではない 未定義動作 これも safely-derived pointer value ではない! ※値としては p と同じだが、結果ではなくて過程で判断 「ラベル a: の位置で GC がかかると p の参照先が回収される」 ???
  • 24. (耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方 ? どうして必要なの? これは safely-derived pointer value T *p = new T; intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555 a: T *q = reinterpret_cast<T*>(x ^ 0x555); T y = *q; こっちは safely-derived pointer value ではない 未定義動作 これも safely-derived pointer value ではない! ※値としては p と同じだが、結果ではなくて過程で判断 「ラベル a: の位置で GC がかかると p の参照先が回収される」 問題は最適化
  • 25. (耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方 ? どうして必要なの? T *p = new T; 以降 p の値は intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555 使われない a: T *q = reinterpret_cast<T*>(x ^ 0x555); T y = *q; ※ p, x, q を同じレジスタに割り当てることが可能 以降 x の値は →ラベル a: の時点で p の値がどこにも存在しない 使われない →p の参照先 = q の参照先が GC の回収対象になる!! →*q で未定義動作 「ラベル a: の位置で GC がかかると p の参照先が回収される」 問題は最適化
  • 26. (耻苍)诲别肠濒补谤别冲谤别补肠丑补产濒别()の使い方 ? C++0xでの正しいコード *p は reachable T *p = new T; = declare_reachable(p); // 偽装前に declare_reachable() を呼ぶ GC対象外 intptr_t x = reinterpret_cast<intptr_t>(p) ^ 0x555 a: // T z = *reinterpret_cast<T*>(x ^ 0x555); // 合法 // 偽装終了時に undeclare_reachable() を呼ぶ T *q = undeclare_reachable(reinterpret_cast<T*>(x ^ 0x555)); T y = *q; 注 ※ declare_reachable した値と同じであれば safely-derived でなくとも逆参照が可能 ※ undeclare_reachable の引数は safely-derived でなくとも reachable であれば良い ※ declare_reachable については「ポインタ値を偽装する」点が問題 a: で関数が別れている場合を考えれば最適化なしで議論は一緒
  • 27. まとめ ? C++0x では最小限の GC サポートがある ? Safely-derived pointer という概念 = GC されていない生きているポインタ値 ? 5 つの関数が追加 ? C++03相当でも規格合致(relaxed) ? しばらくそれ以上の実装はでなさそう? ? ポインタ値を偽装するコードは declare_reachable() / undeclare_reachable() を使って修正する必要がある
  • 28. 参考文献 ? N2670: Minimal Support for Garbage Collection and Reachability-Based Leak Detection (revised) http://www.open- std.org/jtc1/sc22/wg21/docs/papers/2008/ n2670.htm ? Garbage Collection in the Next C++ Standard http://www.hpl.hp.com/techreports/2009/H PL-2009-360.pdf