2010-02-19 9 views
9

Ich verwende einen nicht verwalteten Code, der Zeiger (IntPtr) an große Bildobjekte zurückgibt. Ich benutze die Referenzen, aber nachdem ich mit den Bildern fertig bin, muss ich den von den Zeigern referenzierten Speicher freigeben. Momentan ist das einzige, was den Speicher freigibt, das Herunterfahren meiner gesamten App. Ich muss in der Lage sein, diese Erinnerung aus meiner Anwendung zu befreien.C# Speicher freigeben, der von IntPtr referenziert wird

Hier ist der Aufruf, der den Speicher reserviert. hbitmap ist der Zeiger, der zurückgegeben wird und freigegeben werden muss.

[DllImport("twain_32.dll", EntryPoint = "#1")] 
public static extern TwainResult DsImageTransfer(
    [In, Out] Identity origin, [In] Identity dest, DataGroup dg, 
    DataArgumentType dat, Message msg, ref IntPtr hbitmap); 
+5

Wie wurde der Speicher zugewiesen? –

+0

Dies ist ein Duplikat von http: // stackoverflow.com/fragen/2159150/how-to-frei-intptr-in-c –

+0

OK, also was sagt die Dokumentation für DsImageTransfer mit dem Ergebnis zu tun, wenn Sie damit fertig sind? Wenn Sie den Speicher freigeben müssen, müssen sie Ihnen sagen, wie es geht. –

Antwort

4

Das würde davon abhängen, wie dieser Speicher zugewiesen wurde. Die Klasse Marshal verfügt über Methoden zum Freigeben von Speicher, der über die allgemeinen Interop-Zuweisungsmuster zugewiesen wurde, z. B. FreeCoTaskMem.Wenn der nicht verwaltete Code eine nicht mit Interop kompatible Zuordnungsmethode verwendet, können Sie nicht mit ihm interagieren.

Aktualisiert

Wenn ich eine Vermutung wagen würde, die Funktion # 1 Sie in twain_32.dll aufrufen ist die DS_ENTRY Funktion in einem TWAIN-Anbieter. Der Twain specifications Anruf aus dem Protokoll Ressourcenmanagement Speicher:

Memory Management in TWAIN 2.0 und Höhere
TWAIN erfordert Anwendungen und Quellen jeweils anderen Speicher zu verwalten. Das Hauptproblem besteht darin, Vereinbarungen über die zu verwendenden APIs zu garantieren. TWAIN 2.0 führt vier neue Funktionen ein, die vom Source Manager über DAT_ENTRYPOINT abgerufen werden.

TW_HANDLE PASCAL DSM_MemAllocate (TW_UINT32)
PASCAL DSM_MemFree (TW_HANDLE)
TW_MEMREF PASCAL DSM_MemLock(TW_HANDLE)
void PASCAL DSM_MemUnlock(TW_HANDLE)

Diese Funktionen entsprechen den WIN32 Globalen Funktionen im Speicher in früheren Versionen der TWAIN-Spezifikation erwähnt: GlobalAlloc, GlobalFree, GlobalLock, GlobalUnlock
On MacOS/X rufen diese FunktionenaufNewPtrClear und DisposePtr. Die Sperren und Entsperrfunktionen sind keine Ops, aber müssen sie noch aufgerufen werden. TWAIN 2.0 konforme Anwendungen und Quellen müssen diese Aufrufe auf allen Plattformen (Windows, MacOS/X und Linux) verwenden. Der Source Manager übernimmt die Verantwortung, um sicherzustellen, dass alle Komponenten die gleichen Speicher Management-APIs verwenden.

Also freie Ressourcen sollen Sie DSM_MemFree nennen, die angeblich auf Win32-Plattformen durch GlobalFree oder Marshal.FreeHGlobal umgesetzt würden.

Da dies hauptsächlich Spekulationen von meinem Teil sind, sollten Sie besser mit den Spezifikationen der spezifischen TWAIN-Implementierung, die Sie verwenden, validieren.

+0

GlobalFree arbeitete für mich. Vielen Dank! – Dave

8

Sie benötigen die spezifischen Speicherzuordner Mechanismus zu verwenden, der verwendet wurde, die Erinnerung an erster Stelle zuzuweisen.

Also, wenn Sie COM wurden unter Verwendung von und den IMalloc interface den Speicher zuzuweisen, dann müssen Sie die IntPtr zurück in die Free method auf dieser Umsetzung, um den zugewiesenen Speicher freigeben.

Wenn Sie tatsächlich den COM-Allokator verwenden, der durch einen Anruf an CoGetMalloc zurückgegeben wird, können Sie die static FreeCoTaskMem method über die Marshal class anrufen.

Die Marshal Klasse hat auch ein Verfahren zum Freigeben von Speicher, der durch einen Aufruf von LocalAllocFreeHGlobal genannt zugeordnet ist.

Allerdings, und das ist ein üblicher Fall, wenn der Speicher durch die new operator in C++ oder einen Aufruf von malloc in C zugewiesen wurde, dann müssen Sie eine Funktion in nicht verwalteten Code durch Interop aussetzen, die den Speicher frei werden in geeigneter Weise .

Im Fall von C++ würden Sie eine Funktion verfügbar machen, die einen Zeiger nimmt und einfach delete für diesen Zeiger aufruft. Im Fall von malloc würden Sie eine Funktion erstellen, die einen Zeiger annimmt und free für diesen Zeiger aufruft.

In Bezug auf Ihre Frage, es scheint, dass DsImageTransfer ist eine herstellerspezifische API (eine, die doesn't have much discoverability on the web entweder, fürchte ich), so mehr Informationen über diese spezifische API-Funktion benötigt und wie es Speicher reserviert. Wenn man nur den Handle-Typ kennt (eine HBITMAP in diesem Fall), gibt dies keinen Hinweis darauf, wie es zugeordnet ist. Es kann mit allen oben genannten Mechanismen belegt werden.

Unter der Annahme, es schafft die HBITMAPGDI Object api functions mit (genauer gesagt, die CreateBitmap function), dann könnte man die DeleteObject function mit dem Griff lösen (wie in der Dokumentationsseite für die Object-API-Funktionen GDI).

2

Kommt drauf an. Verfügen Sie über Dokumentation (oder Quellcode) für die nativen Funktionen, die Sie aufrufen?

Systemeigener Code hat keine einzige Zuordnungsfunktion. Dies ist einer der großen Vorteile der CLR.

Wenn ich ein Wettmann wäre, würde ich für GlobalFree gehen. Aber es wird nicht viel Spaß machen, verschiedene APIs zu testen, bis der Code nicht mehr abstürzt.

+0

Whaddaya weiß, ich habe richtig geraten! –

2

Bitte zeigen Sie Ihren nicht verwalteten Code. Es gibt verschiedene Möglichkeiten, Speicher in nicht verwaltetem Land zuzuweisen, und Sie müssen die entsprechenden entsprechenden Mittel zum Aufheben der Zuordnung verwenden. Sie werden wahrscheinlich einen Finalizer und IDisposable am Ende der Umsetzung und die Dispose-Muster zur Durchführung der hier beschrieben: http://www.codeproject.com/KB/cs/idisposable.aspx

+0

Sie können die native Deallokationsfunktion nur von einem Finalizer aus aufrufen, wenn das systemeigene Deallokationssystem threadsicher ist. Es ist besser zu vermeiden, wenn möglich einen Finalizer zu schreiben. –

+0

@Earwicker: Ich hatte nicht nicht-threadsafe Deallocations berücksichtigt - um ehrlich zu sein, dachte ich nicht, dass es unsichere Deallokation Anrufe gab. In der Tat, was würde das bedeuten, Threaded-Code in .Net zu schreiben (wenn die zugrunde liegenden nativen Aufrufe auf Nicht-threadsafe-Deallocators angewiesen sind)? – JMarsch

+1

Die wohldefinierten Microsoft-APIs für die Zuweisung/Freigabe von Speicher sind heutzutage threadsicher (vor VS 2005 gab es eine Option, die nicht thread-sichere Version von 'malloc' /' free' zu ​​verwenden). Aber jeder kann eine native Bibliothek schreiben, die eine ähnliche Schnittstelle freigibt, wo ein Zeiger von einer "Zuweisungs" -Funktion zurückgegeben wird und später an eine "freie" Funktion zurückgegeben werden muss. Sie könnten absolut alles hinter den Kulissen tun, ohne entsprechende Sperren. Sie wissen es nicht, es sei denn, Sie kennen die Interna der Bibliothek. Also habe ich hier über eine zufällige 3rd Party Native Library nachgedacht. –

0

Vielleicht könnten Sie versuchen, ein Bitmap Objekt aus hBitmap Erstellen und Entsorgen Sie es dann.

Bitmap bitmap = Bitmap.FromHBitmap(hBitmap); 
bitmap.Dispose(); 
0

Wie alle anderen darauf hinweisen, hängt es davon ab, wie es zugewiesen wurde. Wenn es sich jedoch wirklich um eine Win32-hbitmap handelt, heben Sie die Zuordnung mit der Win32-Funktion "DeleteObject" auf.

Verwandte Themen