2

A colleague of mine came across an article on codeproject over the weekend which describes the use of the auto_handle method. Given that the article was written in 2006, is that still the right way to handle deterministic disposal for things like file handles?

We've tended to explicitly flush and close file handles and then delete the pointers and null them to be certain the GC has no excuse not to collect them (yes, we know we're super-paranoid). Using something like auto_handle looks like it could help us be more lazy (and we like being lazy when it's safe to do so) but we don't want to start using it's considered bad practice these days and/or there's something better we can use.

4

3 に答える 3

4

C++/CLI は 2005 リリース以降変更されていないため、何か新しいことが起こったと想定する理由はありません。2005 年に有効だったのと同じアドバイスですが、auto_handle はオブジェクトを自動削除する最良の方法ではありません。最初にスタックのセマンティクスを考慮する必要があります。これはほとんどのケースをカバーしています。コンパイラは、コードを除いた C# のusingステートメントと同等の try/finally ブロックとdelete呼び出し (つまり、オブジェクトを破棄) を自動生成します。リンクに示されている例は、次のように行われます。

void Demo1A()
{
    StreamWriter sw("c:\\temp\\test.txt");
    sw.WriteLine("This is a line of text");
}   // <=== Compiler auto-generates the StreamWriter::Dispose call here

オブジェクト宣言に ^ ハットがないことに注意してください。

そして、これはガベージコレクターとはまったく関係がなく、決定論的なリソースのクリーンアップのみと考えてくださいまた、ローカル変数を nullptr に設定することは非常に不適切であることに注意してください。参照の有効期間が実際の使用を超えて不必要に延長される可能性があります。ジッタ オプティマイザは割り当てを削除します。

于 2012-06-18T17:05:15.790 に答える
2

はい、それは決定論的処分を処理する正しい方法です。auto_handle の使用は、C# の using ステートメントに相当する C++/CLI です。

auto_handle (RAII を使用) を使用すると、try-catch を記述する必要なく、例外の安全性を確保できます (つまり、例外がスローされてもオブジェクトは破棄されます)。

参照: C++/CLI リソース管理の混乱

于 2012-06-18T14:28:55.330 に答える
0

管理対象オブジェクトを決定論的に破棄する簡単な方法があると思います。を付けずに宣言するだけで、アンマネージ C++ クラスをオフの^ままにした場合と同じタイプの動作が得られます。*変数が初期化されるとコンストラクターが呼び出され、「デストラクタ」(実際には Dispose メソッド)変数がスコープ外になったときに呼び出されます。

これをコンパイルすると、ローカル変数の場合は try-catch-dispose になり、クラス フィールドの場合はそのクラスの Dispose メソッドに行が追加されます。

これは、デストラクタで Dispose を呼び出す auto_handle と大差ありませんが、構文の方が扱いやすいと思います。

例:

C++/CLI:

public ref class Foo
{
    AutoResetEvent are;

public:
    Foo() : are(false)
    {
        this->are.Set(); // Use a '.' to access members.
    }

    void SomeMethod()
    {
        AutoResetEvent are2(false);
        are2.Set();
    }
};

Reflector の同等の C# で、舞台裏で何をしているかを確認できます。

public class Foo : IDisposable
{
    // Fields
    private readonly AutoResetEvent modreq(IsByValue) are;

    // Methods
    public Foo()
    {
        AutoResetEvent modopt(IsConst) event2 = new AutoResetEvent(false);
        try
        {
            this.are = event2;
            base..ctor();
            this.are.Set();
        }
        fault
        {
            this.are.Dispose();
        }
    }

    public void ~Foo()
    {
    }

    public sealed override void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    [HandleProcessCorruptedStateExceptions]
    protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
    {
        if (flag1)
        {
            try
            {
                this.~Foo();
            }
            finally
            {
                this.are.Dispose();
            }
        }
        else
        {
            base.Finalize();
        }
    }

    public void SomeMethod()
    {
        AutoResetEvent are2 = null;
        AutoResetEvent modopt(IsConst) event2 = new AutoResetEvent(false);
        try
        {
            are2 = event2;
            are2.Set();
        }
        fault
        {
            are2.Dispose();
        }
        are2.Dispose();
    }
}
于 2012-06-18T16:17:45.890 に答える