CA2115: Wywołaj GC.KeepAlive gdy używasz zasobów natywnych
Pozycja | Wartość |
---|---|
Ruleid | CA2115 |
Kategoria | Microsoft.Security |
Zmiana powodująca niezgodność | Niezgodność |
Przyczyna
Metoda zadeklarowana w typie z finalizatorem odwołuje się do System.IntPtr pola lub System.UIntPtr , ale nie wywołuje metody System.GC.KeepAlive.
Uwaga
Ta reguła została przestarzała. Aby uzyskać więcej informacji, zobacz Przestarzałe reguły.
Opis reguły
Odzyskiwanie pamięci finalizuje obiekt, jeśli nie ma więcej odwołań do niego w kodzie zarządzanym. Niezarządzane odwołania do obiektów nie uniemożliwiają odzyskiwania pamięci. Ta reguła wykrywa błędy, które mogą wystąpić, ponieważ kończy się działanie niezarządzanego zasobu, a wciąż jest on używany w kodzie niezarządzanym.
Ta reguła zakłada, że IntPtr i UIntPtr pola przechowują wskaźniki do niezarządzanych zasobów. Ponieważ celem finalizatora jest zwolnienie niezarządzanych zasobów, reguła zakłada, że finalizator zwolni niezarządzany zasób wskazywany przez pola wskaźnika. Ta reguła zakłada również, że metoda odwołuje się do pola wskaźnika, aby przekazać niezarządzany zasób do niezarządzanych kodów.
Jak naprawić naruszenia
Aby naprawić naruszenie tej reguły, dodaj wywołanie metody KeepAlive , przekazując bieżące wystąpienie (this
w języku C# i C++) jako argument. Umieść wywołanie po ostatnim wierszu kodu, w którym obiekt musi być chroniony przed odzyskiwaniem pamięci. Natychmiast po wywołaniu KeepAlivemetody obiekt jest ponownie uznawany za gotowy do odzyskiwania pamięci przy założeniu, że nie ma do niego żadnych zarządzanych odwołań.
Kiedy pomijać ostrzeżenia
Ta reguła sprawia, że niektóre założenia mogą prowadzić do wyników fałszywie dodatnich. Możesz bezpiecznie pominąć ostrzeżenie z tej reguły, jeśli:
Finalizator nie zwalnia zawartości IntPtr pola lub UIntPtr , do których odwołuje się metoda .
Metoda nie przekazuje IntPtr pola lub UIntPtr do niezarządzanych kodów.
Uważnie przejrzyj inne wiadomości przed ich wykluczeniem. Ta reguła wykrywa błędy, które są trudne do odtworzenia i debugowania.
Przykład
W poniższym przykładzie BadMethod
nie zawiera wywołania GC.KeepAlive
metody i dlatego narusza regułę. GoodMethod
zawiera poprawiony kod.
Uwaga
W tym przykładzie przedstawiono przykładowy kod. Mimo że kod jest kompilowany i uruchamiany, ostrzeżenie nie jest wyzwalane, ponieważ niezarządzany zasób nie jest tworzony ani zwalniany.
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 ...
}
}
}
Zobacz też
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla