2010-02-19 13 views
9

Estoy usando algún código no administrado que devuelve punteros (IntPtr) a objetos de imagen grandes. Utilizo las referencias, pero después de que haya terminado con las imágenes, necesito liberar esa memoria a la que hacen referencia los punteros. Actualmente, lo único que libera la memoria es apagar toda mi aplicación. Necesito poder liberar esa memoria desde el interior de mi aplicación.C# desasignar memoria a la que hace referencia IntPtr

Aquí está la llamada a la que asigna la memoria. hbitmap es el puntero que se devuelve y debe desasignarse.

[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

¿Cómo se asignó la memoria? –

+0

Este es un duplicado de http: // stackoverflow.com/questions/2159150/how-to-free-intptr-in-c –

+0

OK, entonces, ¿qué dice la documentación de DsImageTransfer que haga con el resultado cuando haya terminado con él? Si tiene que desasignar la memoria, tienen que decirle cómo hacerlo. –

Respuesta

4

Eso dependería de cómo se haya asignado esa memoria. La clase Marshal tiene métodos para desasignar la memoria asignada a través de los patrones comunes de asignación de interoperabilidad, como FreeCoTaskMem.Si el código no administrado utiliza una forma de asignación no compatible con Interop, entonces no puede interoperar con él.

Actualizado

Si me aventuraría una conjetura, la función # 1 se invoca en twain_32.dll es la función DS_ENTRY en un proveedor de TWAIN. El Twain specifications llamada a cabo el protocolo de gestión de recursos de memoria:

gestión de memoria en TWAIN 2.0 y Superior
TWAIN requiere aplicaciones y Fuentes gestionar la memoria de uno al otro. El problema principal es garantizar el acuerdo sobre las API para su uso. TWAIN 2.0 presenta cuatro funciones nuevas que se obtienen del Administrador de origen a través de 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)

Estas funciones corresponden a la WIN32 memoria global funciones mencionado en las versiones anteriores del TWAIN Especificación: GlobalAlloc, GlobalFree, GlobalLock, GlobalUnlock
En MacOS/X estas funciones llaman NewPtrClear y DisposePtr. La cerradura y las funciones de desbloqueo no funcionan, pero aún deben llamarse. Las aplicaciones y fuentes compatibles con TWAIN 2.0 deben usar estas llamadas en todas las plataformas (Windows, MacOS/X y Linux). El administrador de origen asume la responsabilidad de para asegurarse de que todos los componentes usan la misma memoria API de administración.

Así liberar recursos que se supone que llamar DSM_MemFree, que supuestamente en plataformas Win32 se ejecutaría a través GlobalFree o Marshal.FreeHGlobal.

Dado que esto es principalmente una especulación de mi parte, es mejor validar con las especificaciones de la implementación TWAIN específica que utiliza.

+0

GlobalFree funcionó para mí. ¡Gracias! – Dave

8

Es necesario utilizar el mecanismo asignador de memoria específica que se utilizó para asignar la memoria en el primer lugar.

Por lo tanto, si estuviera usando COM y la IMalloc interface para asignar la memoria, entonces usted tiene que pasar el IntPtr de nuevo a la Free method en que la aplicación con el fin de liberar la memoria asignada.

Si de hecho está utilizando el asignador COM que devuelve una llamada al CoGetMalloc, puede llamar al static FreeCoTaskMem method en el Marshal class.

La clase Marshal también tiene un método para liberar memoria que se asigna mediante una llamada al LocalAlloc llamada FreeHGlobal.

Sin embargo, y este es un caso común, si la memoria se asigna en el new operator en C++, o una llamada a malloc en C, entonces usted tiene que exponer una función en código no administrado a través de interoperabilidad que liberará la memoria apropiada .

En el caso de C++, expone una función que toma un puntero y simplemente llama a delete en ese puntero. En el caso de malloc, crearía una función que toma un puntero y llama al free en ese puntero.

En lo que respecta a su pregunta, parece que DsImageTransfer es una API específica del vendedor (una que doesn't have much discoverability on the web tampoco, me temo), así que se necesita más información sobre esa función API específica y cómo asigna memoria. El solo hecho de conocer el tipo de manejador (un HBITMAP en este caso) no da ninguna indicación de cómo se asigna. Se puede asignar con todos los mecanismos mencionados anteriormente.

Suponiendo que está creando el HBITMAP usando GDI Object api functions (específicamente, el CreateBitmap function), entonces se podría utilizar el DeleteObject function para liberar el asa (según la página de documentación de las funciones de la API de objetos GDI).

2

Depende. ¿Tiene alguna documentación (o código fuente) para las funciones nativas a las que llama?

El código nativo no tiene una sola función de desasignación. Esta es una de las grandes ventajas del CLR.

Si fuera un apostador, iría por GlobalFree. Pero no va a ser muy divertido probar varias API hasta que tu código deje de fallar.

+0

Whaddaya sabe, lo acerté! –

2

Por favor, muestre su código no administrado. Hay diferentes formas de asignar memoria en un terreno no administrado, y debe usar los medios correspondientes correctos de desasignación. Probablemente terminará implementando un Finalizer e IDisposable, e implementando el patrón Dispose como se describe aquí: http://www.codeproject.com/KB/cs/idisposable.aspx

+0

Solo puede llamar a la función de desasignación nativa de un finalizador si el sistema de desasignación nativo es seguro para subprocesos. Es mejor evitar escribir un finalizador si es posible. –

+0

@Earwicker: no había considerado las desasignaciones no seguras de hilos - para ser honesto, no consideré que había llamadas de desasignación inseguras. De hecho, ¿qué significaría escribir código enhebrado en .Net (si las llamadas nativas subyacentes dependen de descriptores de distribución no seguros para el hilo)? – JMarsch

+1

Las API de Microsoft bien definidas para asignación/desasignación de memoria están seguras para subprocesos en estos días (sin embargo, antes de VS 2005 había una opción para usar una versión no segura para subprocesos de 'malloc' /' free'). Pero cualquiera puede escribir una biblioteca nativa que expone una interfaz similar, donde un puntero es devuelto por una función "asignar" y luego debe ser devuelto a una función "libre". Podrían estar haciendo absolutamente todo detrás de las escenas, sin el bloqueo apropiado. No lo sabes a menos que conozcas las partes internas de la biblioteca. Entonces, estaba pensando en una biblioteca nativa de terceros al azar. –

0

Quizás podría tratar de crear un objeto Bitmap de hBitmap y luego deshacerse de él.

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

Como todos los demás señalan, depende de cómo se haya asignado. Sin embargo, si realmente es un hbitmap Win32, entonces lo desasigna con la función Win32 "DeleteObject".

Cuestiones relacionadas