Wenn ich etwas Speicher mit AllocHGlobal reserviere, muss ich es dann mit FreeHGlobal freigeben?

7

Ich habe eine Hilfsmethode geschrieben,

%Vor%

Was ein struct kostet und gibt mir IntPtr zurück. Ich benutze es als solches:

%Vor%

Das Problem ist, dass ich nur das IntPtr für einen Bruchteil einer Sekunde brauche, damit ich es an die C DLL weitergeben kann,

%Vor%

Ich möchte nicht wirklich befürchten müssen, es zu befreien; Ansonsten wächst meine 1-Zeilen-Funktion auf 6:

%Vor%

Gibt es einen besseren Weg, dies zu tun? Wird C # schließlich den Speicher löschen, den er zugewiesen hat?

Wenn nicht, gibt es eine Möglichkeit, den Aufruf an SDL.RenderCopy in einigen using -Anweisungen zu hängen, so dass ich nicht all diese temporäre Variable + explizit nonsense freigeben muss?

    
mpen 10.07.2013, 04:07
quelle

4 Antworten

20

Ja, C # wird nicht automatisch den von Marshal.AllocHGlobal zugewiesenen Speicher freigeben. Dieser Speicher muss mit einem Aufruf von Marshal.FreeHGlobal freigegeben werden, andernfalls wird er geleakt.

Sie könnten einen intelligenten Zeiger erstellen, um die IntPtr

zu umbrechen %Vor%

Mit diesem Wrapper können Sie den Speicher entweder manuell freigeben, indem Sie das Objekt in eine using -Anweisung einschließen oder indem Sie zulassen, dass das Objekt freigegeben wird, wenn der Finalizer ausgeführt wird.

    
shf301 10.07.2013, 04:21
quelle
14

Viele Leute wissen das nicht (und deshalb haben Sie so viele Antworten, dass Sie nicht sagen können), aber .NET ist nur für solche Dinge eingebaut: SafeHandle .

Tatsächlich ist die .NET 2.0-Seite für eine der abgeleiteten Klassen hat ein Beispiel mit AllocHGlobal . Wenn der Finalizer von SafeUnmanagedMemoryHandle aufgerufen wird, ruft er automatisch FreeHGlobal für dich auf. (Wenn Sie eine deterministische Bereinigung wünschen, anstatt nur darauf zu warten, dass der Finalizer darauf zugreift, müssen Sie entweder Close() oder Dispose() explizit aufrufen.)

Es dauert nur ein paar Code-Änderungen auf Ihrer Seite:

%Vor%

Sobald du das tust, wird dein original Copy Beispiel genau so funktionieren, wie du es erwartet hast.

%Vor%

Wenn die beiden Zeiger den Gültigkeitsbereich verlassen und abgeschlossen sind, werden sie anschließend bereinigt. Ich weiß nicht, wie _ptr verwendet wird oder ob Texture eine Klasse ist, die du kontrollierst, aber diese könnten möglicherweise auch auf SafeHandle s gesetzt werden.

UPDATE: Wenn Sie mehr über den Umgang mit nicht verwalteten Ressourcen erfahren möchten (und ein Beispiel für ein besseres Muster für die Implementierung von IDisposable erhalten, als das Beispiel der MSDN) Ich empfehle den Artikel " IDisposable: Was deine Mutter dir nie gesagt hat Über Resource Deallocation "von Stephen Cleary . Er geht in die Tiefe, wie man seine eigenen SafeHandles richtig in den Artikel schreibt.

ANHANG

Hier ist eine Kopie des Beispiels für den Fall, dass die Verbindung jemals tot wird:

%Vor%     
Scott Chamberlain 10.07.2013 05:51
quelle
1

Ja, du musst es befreien, und die Art, wie du es bekommen hast, als dein 6-Zeilen-Programm ist ziemlich effizient. Es ist der Kompromiss, den Sie machen, wenn Sie den Müllsammler verlassen.

    
Keith Nicholas 10.07.2013 04:15
quelle
0

Leider gibt es dafür keine automatische Methode. Wenn Sie AllocHGlobal aufrufen, müssen Sie explizit damit angeben FreeHGlobal (es sei denn, Sie sind mit potenziell massivem Speicher zufrieden Lecks).

  

Dieser Speicher muss mithilfe der Marshal.FreeHGlobal Methode.

Was ich in der Vergangenheit getan habe, ist, meine AllocHGlobal -Zuordnungen in einer IDisposable -Wrapper-Klasse einzupacken, wobei Dispose() auf dem Zeiger FreeHGlobal aufruft. Auf diese Weise konnte ich sie in eine using -Anweisung einfügen.

    
Jonathon Reinhart 10.07.2013 04:15
quelle

Tags und Links