2010-02-19 12 views
9

Sto usando un codice non gestito che sta restituendo i puntatori (IntPtr) agli oggetti immagine di grandi dimensioni. Uso i riferimenti ma dopo aver finito con le immagini, ho bisogno di liberare quella memoria a cui fanno riferimento i puntatori. Attualmente, l'unica cosa che libera la memoria è quella di spegnere la mia intera app. Devo essere in grado di liberare quella memoria dall'interno della mia applicazione.C# deallocate la memoria a cui fa riferimento IntPtr

Questa è la chiamata che alloca la memoria. hbitmap è il puntatore che viene restituito e deve essere deallocato.

[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

Come è stata allocata la memoria? –

+0

Questo è un duplicato di http: // StackOverflow.it/questions/2159150/how-to-free-intptr-in-c –

+0

OK, cosa dice la documentazione di DsImageTransfer sul risultato quando hai finito? Se ti viene richiesto di deallocare la memoria, devono dirti come si fa. –

risposta

4

Ciò dipenderà dal modo in cui è stata allocata la memoria. La classe Marshal ha metodi per deallocare la memoria allocata attraverso i modelli di allocazione di interoperabilità comuni, ad esempio FreeCoTaskMem.Se il codice non gestito utilizza un metodo di allocazione non compatibile con Interop, non è possibile utilizzarlo per l'interoperabilità.

Aggiornato

Se mi azzarderei una supposizione, la funzione # 1 si richiama nel Twain_32.dll è la funzione DS_ENTRY in un fornitore di TWAIN. Il Twain specifications chiamata fuori il protocollo di gestione delle risorse della memoria:

gestione della memoria in TWAIN 2.0 e superiore
TWAIN richiede applicazioni e Fonti di gestire la memoria di ciascuno. Il problema principale è garantire l'accordo sulle API da utilizzare. TWAIN 2.0 introduce quattro nuove funzioni ottenute dal gestore sorgente tramite DAT_ENTRYPOINT.

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)

Queste funzioni corrispondono al WIN32 globale memoria funzioni menzionato nelle versioni precedenti del TWAIN Specification: GlobalAlloc, GlobalFree, GlobalLock, GlobalUnlock
On MacOS/X queste funzioni chiamano NewPtrClear e DisposePtr. Le funzioni di blocco e di sblocco sono non operative, ma è necessario chiamare ancora . TWAIN 2.0 compatibile Applicazioni e Fonti deve utilizzare queste chiamate su tutte le piattaforme (Windows, MacOS/X e Linux). Il gestore sorgente assume la responsabilità dello per assicurarsi che tutti i componenti utilizzino la stessa memoria API di gestione .

Quindi, per liberare risorse che dovresti chiamare DSM_MemFree, che presumibilmente su piattaforme Win32 verrebbe attuato attraverso GlobalFree, o Marshal.FreeHGlobal.

Poiché si tratta principalmente di speculazioni da parte mia, è meglio convalidare con le specifiche dell'implementazione TWAIN specifica che si utilizza.

+0

GlobalFree ha funzionato per me. Grazie! – Dave

8

È necessario utilizzare il meccanismo allocatore di memoria specifico che è stato utilizzato per allocare la memoria, in primo luogo.

Quindi, se si sta utilizzando COM e il IMalloc interface per allocare la memoria, allora dovete passare il IntPtr indietro al Free method su quel attuazione al fine di liberare la memoria allocata.

Se si utilizza effettivamente l'allocatore COM che viene restituito da una chiamata a CoGetMalloc, è possibile chiamare lo static FreeCoTaskMem method su Marshal class.

La classe Marshal ha anche un metodo per liberare memoria assegnata tramite una chiamata a LocalAlloc denominata FreeHGlobal.

Tuttavia, e questo è un caso comune, se la memoria è stata allocata dal new operator in C++, o una chiamata alla malloc in C, allora si deve esporre una funzione nel codice non gestito attraverso interoperabilità che libererà la memoria opportunamente .

Nel caso di C++, esporre una funzione che accetta un puntatore e chiama semplicemente delete su quel puntatore. Nel caso di malloc, si creerà una funzione che accetta un puntatore e chiama free su quel puntatore.

Per quanto riguarda specifiche alla tua domanda, sembrerebbe che DsImageTransfer è un'API specifico del fornitore (uno che doesn't have much discoverability on the web sia, temo), quindi sono necessarie maggiori informazioni su questa funzione API specifica e come si alloca la memoria. Solo conoscendo il tipo di maniglia (uno HBITMAP in questo caso) non fornisce alcuna indicazione su come è allocato. Può essere assegnato con tutti i meccanismi sopra menzionati.

Supponendo che sta creando il HBITMAP utilizzando GDI Object api functions (in particolare, la CreateBitmap function), allora si potrebbe utilizzare il DeleteObject function per rilasciare la maniglia (come per la pagina di documentazione per le funzioni oggetto API GDI).

2

Dipende. Hai qualche documentazione (o codice sorgente) per le funzioni native che stai chiamando?

Il codice nativo non ha una funzione di deallocazione singola. Questo è uno dei grandi vantaggi del CLR.

Se fossi un uomo delle scommesse, andrei per GlobalFree. Ma non sarà molto divertente provare varie API finché il tuo codice non si arresta.

+0

Whaddaya lo so, ho indovinato! –

2

Si prega di mostrare il codice non gestito. Esistono diversi modi per allocare la memoria in una terra non gestita e devi utilizzare i corrispondenti metodi corretti di deallocazione. Probabilmente si finirà per implementare un Finalizer e IDisposable e implementando il pattern Dispose come descritto qui: http://www.codeproject.com/KB/cs/idisposable.aspx

+0

È possibile chiamare la funzione di deallocation nativa solo da un finalizzatore se il sistema di deallocation nativo è thread-safe. È meglio evitare di scrivere un finalizzatore se possibile. –

+0

@Earwicker: non avevo considerato deallocazioni non a rischio di errore - ad essere onesti, non ritenevo che ci fossero chiamate di dealbase non sicure. In effetti, cosa significherebbe scrivere codice con thread in .Net (se le chiamate native sottostanti si basano su deallocator non-thread-safe)? – JMarsch

+1

Le API Microsoft ben definite per l'allocazione/deallocazione della memoria sono thread-safe al giorno d'oggi (prima di VS 2005 c'era un'opzione per usare la versione non protetta da thread di 'malloc' /' free', comunque). Ma chiunque può scrivere una libreria nativa che espone un'interfaccia simile, in cui un puntatore viene restituito da una funzione "allocare" e deve essere successivamente restituito a una funzione "libera". Potrebbero fare assolutamente qualsiasi cosa dietro le quinte, senza il blocco appropriato. Non lo sai se non conosci gli interni della biblioteca. Quindi stavo pensando a qualche libreria nativa casuale di terze parti. –

0

Forse si potrebbe provare a creare un oggetto Bitmap da hBitmap e quindi eliminarlo.

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

Come tutti gli altri fanno notare, esso dipende da come è stato assegnato. Tuttavia, se è davvero un hbitmap Win32, lo si disalloca con la funzione "DeleteObject" di Win32.

Problemi correlati