東方算程譚

Oriental Code Talk ── επιστημηが与太をこく、弾幕とは無縁のシロモノ。

目次

Blog 利用状況

ニュース

著作とお薦めの品々は

著作とお薦めの品々は
東方熱帯林へ。

あわせて読みたい

わんくま

  1. 東京勉強会#2
    C++/CLI カクテル・レシピ
  2. 東京勉強会#3
    template vs. generics
  3. 大阪勉強会#6
    C++むかしばなし
  4. 東京勉強会#7
    C++むかしばなし
  5. 東京勉強会#8
    STL/CLRによるGeneric Programming
  6. TechEd 2007 @YOKOHAMA
    C++・C++/CLI・C# 適材適所
  7. 東京勉強会#14
    Making of BOF
  8. 東京勉強会#15
    状態遷移
  9. 名古屋勉強会#2
    WinUnit - お気楽お手軽UnitTest

CodeZine

  1. Cで実現する「ぷちオブジェクト指向」
  2. CUnitによるテスト駆動開発
  3. SQLiteで組み込みDB体験(2007年版)
  4. C++/CLIによるCライブラリの.NET化
  5. C# 1.1からC# 3.0まで~言語仕様の進化
  6. BoostでC++0xのライブラリ「TR1」を先取りしよう (1)
  7. BoostでC++0xのライブラリ「TR1」を先取りしよう (2)
  8. BoostでC++0xのライブラリ「TR1」を先取りしよう (3)
  9. BoostでC++0xのライブラリ「TR1」を先取りしよう (4)
  10. BoostでC++0xのライブラリ「TR1」を先取りしよう (5)
  11. C/C++に対応した、もうひとつのUnitTestFramework ─ WinUnit
  12. SQLiteで"おこづかいちょう"
  13. STL/CLRツアーガイド
  14. マージ・ソート : 巨大データのソート法
  15. ヒープソートのアルゴリズム
  16. C++0xの新機能「ラムダ式」を次期Visual Studioでいち早く試す
  17. .NETでマンデルブロ集合を描く
  18. .NETでマンデルブロ集合を描く(後日談)
  19. C++/CLI : とある文字列の相互変換(コンバージョン)
  20. インテルTBBによる選択ソートの高速化
  21. インテルTBB3.0 によるパイプライン処理
  22. Visual C++ 2010に追加されたSTLアルゴリズム
  23. Visual C++ 2010に追加されたSTLコンテナ「forward_list」
  24. shared_ptrによるObserverパターンの実装
  25. .NETでマンデルブロ集合を描く(番外編) ── OpenCLで超並列コンピューティング
  26. StateパターンでCSVを読む
  27. 状態遷移表からStateパターンを自動生成する
  28. 「ソートも、サーチも、あるんだよ」~標準C++ライブラリにみるアルゴリズムの面白さ
  29. インテルTBBの同期メカニズム
  30. なぜsetを使っちゃいけないの?
  31. WPFアプリケーションで腕試し ~C++でもWPFアプリを
  32. C++11 : スレッド・ライブラリひとめぐり
  33. Google製のC++ Unit Test Framework「Google Test」を使ってみる
  34. メールでデータベースを更新するココロミ
  35. Visitorパターンで遊んでみたよ
  36. Collection 2題:「WPFにバインドできる辞書」と「重複を許す検索set」
  37. Visual C++ 2012:stateless-lambdaとSQLiteのぷち拡張
  38. 「Visual C++ Compiler November 2012 CTP」で追加された6つの新機能

@IT

  1. Vista時代のVisual C++の流儀(前編)Vista到来。既存C/C++資産の.NET化を始めよう!
  2. Vista時代のVisual C++の流儀(中編)MFCから.NETへの実践的移行計画
  3. Vista時代のVisual C++の流儀(後編) STL/CLRによるDocument/Viewアーキテクチャ
  4. C++開発者のための単体テスト入門 第1回 C++開発者の皆さん。テスト、ちゃんとしていますか?
  5. C++開発者のための単体テスト入門 第2回 C++アプリケーションの効率的なテスト手法(CppUnit編)
  6. C++開発者のための単体テスト入門 第3回 C++アプリケーションの効率的なテスト手法(NUnit編)

AWARDS


Microsoft MVP
for Visual Developer - Visual C++


Wankuma MVP
for いぢわる C++


Nyantora MVP
for こくまろ中国茶

Xbox

Links

記事カテゴリ

書庫

日記カテゴリ

こうですか? わかりません!

添削お願いしますぅ > えらいひと

/*
 * 可及的速やかに破棄したい
 * unmanaged-resourceを持ったクラスのテンプレ
 */

public class SampleClass : System.IDisposable {

  private object unmanaged_resource; // マネージ対象外リソース
  protected bool disposed = false; // Dispose()済みならtrue

  // コンストラクタ
  public SampleClass() {
    // ここでnewしなければならんわけじゃないが
    unmanaged_resource = new object();
  }

  // Dispose()後にメソッドが呼ばれたときの用心のため、
  // 各public/protectedメソッドはその処理に先立ちこいつを呼ぶことを推奨する

  protected void assertDisposed() {
    if ( disposed ) {
      throw new System.ObjectDisposedException(
        this.GetType().ToString(),
        "has been disposed.");
    }
  }

  // Dispose()の実処理はココで行う
  protected void doDispose(bool disposing) {
    if ( !disposed ) {
      if ( disposing ) {
       // managed-resourceを持っている
       // ならここでDispose()
      }
      // ここでunmanaged-resourceを廃棄
    }
    disposed = true;
  }

  // Dispose
  public virtual void Dispose() {
    doDispose(true);
    // 後続するFinaraize()を抑止
    System.GC.SuppressFinalize(this); 
  }

  // デストラクタ(=Finalize)
  public ~SampleClass() {
    doDispose(false);
  }

}

※ Finalize→~SampleClass に修正しました

投稿日時 : 2008年6月26日 9:14

コメントを追加

# re: こうですか? わかりません! 2008/06/26 9:34 シャノン

> doDispose

一般的には、その名前も Dispose。

> public virtual void Finalize()

C# なら ~SampleClass()
base.Finalize の呼び出しは不要。

# re: こうですか? わかりません! 2008/06/26 9:47 επιστημη

>> doDispose
> 一般的には、その名前も Dispose。

えと、DisposeをすっとばしてFinalizeされちゃった
ときを考慮してこう書いたんだけど、心配しすぎ?
# あ、単にメソッド名? Dispose(bool) でいーぢゃん?

> C# なら ~SampleClass()

あーそかそか

# re: こうですか? わかりません! 2008/06/26 9:56 シャノン

> えと、DisposeをすっとばしてFinalizeされちゃった
> ときを考慮してこう書いたんだけど、心配しすぎ?

どういう想定か良くわかんないです…。

# re: こうですか? わかりません! 2008/06/26 10:02 επιστημη

あ、いや、そんなシチュエーションが"あり得ない"のなら
僕が心配性なだけなんですが...
newしたまんまほっとくと"必ずDisposeされるとは限らない"んじゃなかったっけ。
それでもFinalizeは定義していれば必ず動くから、
そのタイミングでunmanaged-resourceを始末できるかな、と。

# re: こうですか? わかりません! 2008/06/26 10:15 シャノン

> newしたまんまほっとくと"必ずDisposeされるとは限らない"んじゃなかったっけ。

Finalize(~SampleClass)から Dispose を呼んでいるので、Finalize されれば Dispose されます。
Finalize されない状況というのは、
・プロセス終了までマネージドメモリをほとんど使わなかった
・AppDomain のアンロードなど、異常な状況が発生した
のいずれかです。

前者は、アンマネージドリソースの使用量がパフォーマンスネックになるほどなら、明示的に Dispose するしかありません。
プロセス終了まで放っといてもパフォーマンスに影響を与えない程度なら、それもいいでしょう。
(これはC++で作ったアンマネージドアプリでも同じですよね)

後者は、CriticalFinalizerObject から派生させると、そういう場合でも確実に解放できるらしいです。
.NET Framework 2.0 のアンマネージドリソースを扱う類のクラスはそうなっています。

# re: こうですか? わかりません! 2008/06/26 10:16 シャノン

> # あ、単にメソッド名? Dispose(bool) でいーぢゃん?

あ、そうかも。
引数なし(IDisposable.Dispose)とDispose(bool)でオーバーロードにします。

# Dispose パターン 2008/06/26 10:27 dai-okuno

MS推奨のDisposeパターンではこんな感じだった気がします。
パターンというよりはイディオムと呼ぶべきなんでしょうけど。

/// <remarks>
/// 派生クラスでは適切にオーバーライドすること。
/// <remarks>
protected virtual Dispose(bool disposing){
if(!disposed){
if(disposing){
// Release managed resources
}
// Release unmanaged resources
}
}

public void Dispose(){
Dispose(true);
GC/SuppressFinalize();
}

~SampleClass(){
Dispose(false);
}

# re: こうですか? わかりません! 2008/06/26 10:29 biac

IDisposable を実装するときは、 毎度毎度悩みます。 何回やっても忘れちゃう。
C++ のザク^H^Hデストラクタとは違うのだよ、 とは覚えていても、 どう違うかを覚えてられないのはナゼ? f(^^;

そんなわけで、 そのたびに読むページ。
http://www.microsoft.com/japan/msdn/net/mag00/GCI.aspx

# re: こうですか? わかりません! 2008/06/26 10:30 επιστημη

MSタンのパターンがそれなら、僕のはほとんど正解っすね♪

# re: こうですか? わかりません! 2008/06/26 10:48 dai-okuno

ちなみに、派生クラスではDispose(bool)をオーバーライドします。

詳しくは以下のページで。
http://msdn.microsoft.com/ja-jp/library/fs2xkftw(VS.80).aspx

スレッドセーフにするには工夫が必要かも。

protected override void Dispose(bool disposing){
 if(!disposed){
  try{
   if(disposing){
    // Release additional managed resource
   }
   // Release additional unmanaged resource
   this.disposed = true;
  }
  finally{
   base.Dispose(true);
  }
 }
}

# re: こうですか? わかりません! 2008/06/26 11:14 渋木宏明(ひどり)

>Dispose()後にメソッドが呼ばれたときの用心のため

「オブジェクトインスタンスが存命中、そのオブジェクトが実装する IDisposable.Dispose() はたかだか1回しか呼んではいけない」という決まりはないので、これが必要かどうかはそのクラスの要件・設計次第になりますね。

# re: こうですか? わかりません! 2008/06/26 11:21 渋木宏明(ひどり)

あと、関連事項として

SafeHandle クラス
http://msdn.microsoft.com/ja-jp/library/system.runtime.interopservices.safehandle(VS.80).aspx

の使用を推奨します。

# re: こうですか? わかりません! 2008/06/26 13:07 NyaRuRu

>Finalize されない状況というのは、
>・プロセス終了までマネージドメモリをほとんど使わなかった
>・AppDomain のアンロードなど、異常な状況が発生した
>のいずれかです。

あれ? そうなんですか?
前者は正常終了であればプロセス終了時にファイナライザが呼ばれるはずですし,後者は「AppDomain のアンロード」が異常事態に見えてしまいます.ファイナライザが呼ばれないのは,「異常な AppDomain のアンロード」時のことでは?

http://msdn.microsoft.com/ja-jp/library/ms231056.aspx

この分類で行くと,RudeUnload とか RudeAbort と呼ばれているのが異常事態ですね.CriticalFinalizerObject や,その派生クラスである SafeHandle などは,そういった異常事態でも何かしらの作業を可能にしてくれます.

# re: こうですか? わかりません! 2008/06/26 13:14 シャノン

> 前者は正常終了であればプロセス終了時にファイナライザが呼ばれるはずですし

そうなんですか?
ファイナライザ=オブジェクトがガベコレされるときに走るもの→ガベージコレクタが働かなければ実行されない
かと思ってました。

> ファイナライザが呼ばれないのは,「異常な AppDomain のアンロード」時のことでは?

ですね。
正直、そっちのことはあまりよく知らんのです。知ったかぶりで言いました。

> http://msdn.microsoft.com/ja-jp/library/ms231056.aspx

microsoft.com が死んでますね…

# re: こうですか? わかりません! 2008/06/26 14:18 NyaRuRu

>そうなんですか?
>ファイナライザ=オブジェクトがガベコレされるときに走るもの→ガベージコレクタが働かなければ実行されない
>かと思ってました。

このあたりですかね.

http://msdn.microsoft.com/ja-jp/library/ms164399.aspx

http://msdn.microsoft.com/ja-jp/library/ms231430.aspx

タイトル
名前
URL
コメント