2016-07-19 6 views
2

Ich bin Marshalling Daten über C/C# Grenze. Ich habe die folgende Struktur:Muss ich ein IntPtr innerhalb eines Callbacks freigeben?

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct Message 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] 
    public string From; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
    public string Subject; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 
    public string Body; 
} 

Der Rückruf ist wie folgt definiert:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
delegate void MessageReceiveDelegate([In]IntPtr ptrToMessage); 

private void MessageReceiveCallback(IntPtr ptrToMessage) 
{ 
    Message message = (Message)Marshal.PtrToStructure(ptrToMessage, typeof(Message)); 

    Marshal.FreeHGlobal(ptrToMessage); //This throws COMException! 
} 

Meine Frage ist, kann ich IntPtr (ptrToMessage) über die Freigabe innerhalb des Rückrufs kümmern Speicherlecks zu vermeiden? Ich habe versucht Aufruf FreeHGlobal drauf, aber mit folgender Ausnahme am Ende:

‚System.Runtime.InteropServices.COMException‘ ist in mscorlib.dll aufgetreten

Weitere Informationen Eine nicht behandelte Ausnahme des Typs: Der Griff ist ungültig. (Ausnahme von HRESULT: 0x80070006 (E_HANDLE))

So bin ich entweder etwas falsch zu machen, oder der Speicher nicht von mir freigegeben werden.

+2

Wenn Ihr Code nicht der Eigentümer des 'Intptr' ist (d. H. Ihn nicht zugeordnet hat), sollten Sie ihn nicht freigeben, es sei denn, die API dokumentiert dies. Es ist auch möglich, dass Sie eine andere "Marshal" -Methode verwenden müssen, um den Puffer wie "Marshal.FreeCoTaskMem" – GreatAndPowerfulOz

+0

@ Great.And.Powerful.Oz zu befreien. Ich habe den IntPtr nicht zugewiesen. Es wird mir von der 3rd-Party-Bibliothek übergeben. Ich habe zuvor versucht, FreeCoTaskMem zu verwenden, aber das verursachte einen Absturz, anstatt nur eine Ausnahme. – Eternal21

Antwort

2

Dieser Speicher wurde von Ihnen zugewiesen? Wenn ja - ja, höchstwahrscheinlich müssen Sie es selbst freigeben. Wenn nein ...

Welche API verwenden Sie? Gibt es an, dass Sie diese Erinnerung freigeben müssen? Wofür wurde der Allokator verwendet? Definiert es eine Möglichkeit, dieses Gedächtnis freizugeben? Wenn ja - ja, du musst es freigeben. Wenn nein ...

Nein, Sie sollten es nicht freigeben. Zum Beispiel könnte es nur ein Zeiger auf die Struktur sein, die auf dem Stapel zugeordnet ist.

Wenn Sie einen Zeiger haben, heißt das nicht, dass es sich um einen dynamisch zugewiesenen Speicher handelt.

+0

Ich habe den IntPtr nicht zugeordnet. Es kommt aus einer C-Bibliothek von Drittanbietern als ein Argument des Rückrufs. – Eternal21

+0

@ Eternal21 Gibt diese Bibliothek an, dass Sie diesen Speicher freigeben müssen? – lorond

+0

Nein, ich versuche, den Anbieter zu kontaktieren, um das herauszufinden. – Eternal21

Verwandte Themen