2012-02-16 14 views
3

は、次のC++/CLIのコードフラグメントを考えてみましょう:オブジェクトは実行中にガベージコレクトされますか?

public ref class MyData 
{ 

private: 
    UnmanagedObject* pobj; 

public: 
    MyData() 
    { 
    pobj = ... // acquire unmanaged pointer 
    } 

    !MyData() 
    { 
    delete pobj; // finalizer 
    pobj = NULL; 
    } 

    void DoSomething() 
    { 
    // next line calls a native method that has no knowledge of .NET 
    CallToNativeMethod(data->pobj); 
    } 

    static void Test() 
    { 
    MyData^ data = gcnew MyData(); 
    data->DoSomething() 
    } 
} 

このクラスは、いくつかの非管理APIの.NETラッパーを表します。私のプロジェクトでは、現在、トレースするのが難しいバグを扱っています。MyDataのインスタンスは、DoSomething()の実行中にガベージコレクションされているようです。ここで私は起こる信じるものである:(!)

  1. MyData
  2. DoSomething()と呼ばれるDoSomething()インスタンスメソッドのインスタンスを作成すると呼ばれる静的メソッドTest()は、ネイティブメソッド
  3. しばらく呼び出しますネイティブメソッドが実行されているときに、ガベージコレクタがMyDataのインスタンスを収集し、ファイナライザを呼び出す
  4. ファイナライザは、ネイティブの私によって使用されるpobjを削除します。

    1. が実際に可能上記のようなシナリオです:THOD まだプログラムが

    私の2つの質問がクラッシュ...

  5. まあを実行していますか?インスタンスメソッドがまだ実行されている間に、オブジェクトがファイナライズされるという事実をかなり引き継ぐことはできません。
  6. この問題を解決するには、どのような方法が良いですか?そうするための "安全")? のインスタンス変数の後にネイティブメソッドが実行された場合、そのトリックは変更されますが、それはアドホックです。

EDIT(追加情報):ネイティブメソッドからバブルアップ、及びTest()try..catchによって捕捉することができるAccessViolationExceptionを持つコードがクラッシュ。デバッグのために、私は、次の実行順序を明らかにし、ロギング呼び出しのカップルを、挿入:

  • ネイティブメソッドはファイナライザは例外がキャッチされ
  • 実行され
  • 入力された(しかし、終了したことはありません)され
  • +0

    オブジェクトがガベージコレクションされていることを確認していますか? –

    +0

    MyDataのインスタンスが収集される可能性はありません。結局それはTestメソッドに根ざしています。例外は何を言いますか? –

    +0

    @Matt:ポストを編集していくつかの情報を追加しました –

    答えて

    0

    GC::KeepAlive(data)をTest()メソッドの末尾に追加する必要があります。

    CallToNativeMethodが呼び出しを別のスレッドに呼び出してすぐに戻ると、管理対象データオブジェクトとGC参照がかなり早くスコープから外れてしまい、再びガベージコレクションされる危険があることに注意してください。その場合、KeepAliveを呼び出す何らかの種類の通知コードを作成し、それが信号を受け取るまで作成する必要があります。

    関連する問題