3

新しい機能を活用するために、プロジェクトのターゲット フレームワークを .NET 3.5 から .NET 4.0 に変更しました。しかし、プログラムを開始すると、次のようになります。

タイプ 'BitmapHandle' の SafeHandle または CriticalHandle は、値 0xB605123D のハンドルを適切に解放できませんでした。これは通常、ハンドルが別の手段 (DangerousGetHandle を使用してハンドルを抽出し、直接閉じるか、その周りに別の SafeHandle を構築するなど) によって誤って解放されたことを示します。

しかし、この原因をどこから探し始めればよいかさえわかりません。これ以上の情報は得られず、3.5 ではすべて問題ありませんでした。

4

1 に答える 1

3

これは、WPF SplashScreen クラスのバグです。.NET 4.6 では、BitmapHandle は SafeHandle クラスであり、そのReleaseHandle()メソッドは次のようになります。

    protected override bool ReleaseHandle()
    {
        return UnsafeNativeMethods.DeleteObject(handle);
    }

これは非常に正しいです。何が起こっても、GDI ビットマップ オブジェクトが適切に破棄されることが保証されます。バグはSplashScreen.DestroyResources()メソッドに存在し、非常に役立ちます。

    private void DestroyResources()
    {
        //...
        if (_hBitmap != null && !_hBitmap.IsClosed)
        {
            UnsafeNativeMethods.DeleteObject(_hBitmap.MakeHandleRef(null).Handle);
            _hBitmap.Close();
            _hBitmap = null;
        }
        //...
    }

への 2 回の呼び出しDeleteObject、1 回が多すぎます。デバッガーには、このようなバグを監視する MDA (Managed Debugging Assistant) があり、ReleaseHandle() が失敗してステップインするのを確認します。MDA はデフォルトでオフになっているため (賢明ではありません)、通常これは表示されません。デバッグ > 例外 > マネージ デバッグ アシスタント > ReleaseHandleFailed. 通知の受信を停止するには、チェックを外します。

このようなバグは非常に厄介で、リサイクル攻撃を処理するための扉を開きます。ただし、実際に悪用される可能性は非常に低く、Close() 呼び出しは DeleteObject() 呼び出しの直後に続き、ビットマップは特に危険ではありません :) 技術的には事故が発生する可能性があります。別のスレッドで同時に GDI オブジェクトを作成する必要があります。これは、WPF アプリではあまり発生しません。

connect.microsoft.com でバグを報告できます。この Q+A へのリンクで十分です。

于 2015-10-11T07:40:52.103 に答える