CA2115: ネイティブ リソースを使用しているときには GC.KeepAlive を呼び出します
TypeName |
CallGCKeepAliveWhenUsingNativeResources |
CheckId |
CA2115 |
[カテゴリ] |
Microsoft.Security |
互換性に影響する変更点 |
なし |
原因
ファイナライザーを持つ型で宣言されたメソッドで、System.IntPtr フィールドまたは System.UIntPtr フィールドを参照していますが、GC.KeepAlive を呼び出していません。
規則の説明
ガベージ コレクションは、マネージ コードでオブジェクトが参照されなくなるとオブジェクトを終了します。アンマネージ コードでのオブジェクト参照は、ガベージ コレクションを防ぎません。この規則では、アンマネージ コードでまだ使用されているのに、アンマネージ リソースが終了されたときに発生する可能性のあるエラーを検出します。
この規則では、IntPtr と UIntPtr の各フィールドに、アンマネージ リソースへのポインターが格納されていると仮定しています。ファイナライザーの目的はアンマネージ リソースを解放することなので、この規則では、ポインターのフィールドによって示されるアンマネージ リソースをファイナライザーが解放すると仮定します。また、この規則では、メソッドはポインター フィールドを参照し、アンマネージ リソースをアンマネージ コードに渡していると仮定します。
違反の修正方法
この規則違反を修正するには、KeepAlive の呼び出しをメソッドに追加し、現在のインスタンス (C# と C++ では this) を引数として渡します。この呼び出しは、ガベージ コレクションからオブジェクトを保護するコードの最終行の後に指定します。KeepAlive を呼び出した直後から、ガベージ コレクションは、オブジェクトに対するマネージ参照がないと改めて仮定します。
警告を抑制する状況
この規則には、誤った規則違反がレポートされる仮定があります。次の場合、この規則による警告を抑制しても安全です。
警告を除外する前に、他のメッセージを慎重に再確認します。この規則では、再生やデバッグが困難なエラーが検出されます。
使用例
このため、次の例では、BadMethod は GC.KeepAlive の呼び出しが含まれておらず、規則に違反することになります。GoodMethod に修正後のコードが格納されます。
[!メモ]
この例では、アンマネージ リソースが作成されず、解放されないため、コードをコンパイルして実行しますが、警告が発生しない擬似コードです。
using System;
namespace SecurityRulesLibrary
{
class IntPtrFieldsAndFinalizeRequireGCKeepAlive
{
private IntPtr unmanagedResource;
IntPtrFieldsAndFinalizeRequireGCKeepAlive()
{
GetUnmanagedResource (unmanagedResource);
}
// The finalizer frees the unmanaged resource.
~IntPtrFieldsAndFinalizeRequireGCKeepAlive()
{
FreeUnmanagedResource (unmanagedResource);
}
// Violates rule:CallGCKeepAliveWhenUsingNativeResources.
void BadMethod()
{
// Call some unmanaged code.
CallUnmanagedCode(unmanagedResource);
}
// Satisfies the rule.
void GoodMethod()
{
// Call some unmanaged code.
CallUnmanagedCode(unmanagedResource);
GC.KeepAlive(this);
}
// Methods that would typically make calls to unmanaged code.
void GetUnmanagedResource(IntPtr p)
{
// Allocate the resource ...
}
void FreeUnmanagedResource(IntPtr p)
{
// Free the resource and set the pointer to null ...
}
void CallUnmanagedCode(IntPtr p)
{
// Use the resource in unmanaged code ...
}
}
}
参照
関連項目
Implementing Finalize and Dispose to Clean Up Unmanaged Resources