2012-01-26 14 views
7

Escribo un módulo en C# que exporta algunas funciones para usar en C. Necesito asignar algo de memoria para que algunas estructuras pasen entre C < -> C#.Cualquier diferencia entre malloc y Marshal.AllocHGlobal?

Lo que asigno en C Lo hago con malloc, y en C# lo hago con Marshal.AllocHGlobal() (para asignar memoria no administrada para pasarla a C).

¿Hay algún problema si libero() la memoria asignada con Marshal.AllocHGlobal, y si libero la memoria con Marshal.FreeHGlobal() que se asignó con malloc?

Gracias

+0

Gracias por todas las respuestas – bzamfir

+0

Gracias. En realidad, lo que hice fue crear en mi lib las funciones exportadas AllocateMem, y FreeMem, que recomendé utilizar al llamar programas, al crear estructuras que se pasan a lib. Pero me preguntaba si uno no está cumpliendo con esta regla y le paso a mi lib algunas estructuras asignadas con malloc (o cualquier otra cosa), ¿qué debería pasar? – bzamfir

+0

El problema es que las estructuras tienen algunos punteros a char (para cadenas) que tengo que asignar y pasar al código de llamada. ¿Y qué ocurre si el código de llamada intenta liberar esa memoria con free()? Es por eso que creé FreeMem, que implementé con FreeHGlobal, para ser utilizado para liberar memoria en prog. De lo contrario, es responsabilidad del programador del código de llamada. – bzamfir

Respuesta

15

La regla de oro es que se debe anular la planificación de la misma pila que se utilizó para asignar la memoria.

Si lo asigna con malloc(), debe desasignarlo con el free() del mismo C RTL. Y del mismo modo, en el lado administrado, AllocHGlobal() debe estar equilibrado por FreeHGlobal().

Ahora, AllocHGlobal() se implementa llamando a la función Win32 LocalAlloc. Por lo tanto, puede liberar dicha memoria con una llamada al LocalFree en el lado nativo. Y viceversa.

Si desea utilizar un montón compartido entre nativo y administrado, es más común usar el montón COM. En el lado nativo, use CoTaskMemAlloc() y CoTaskMemFree(). En el lado administrado, use Marshal.AllocCoTaskMem() y Marshal.FreeCoTaskMem().

Sin embargo, debe evitar diseñar el sistema de esta manera. Es mucho más simple seguir una regla de que toda la memoria asignada en el lado gestionado se desasigna, y también para el lado nativo. Si no sigue esa regla, pronto perderá la pista de quién es responsable de qué.

4

Puede haber o no un problema, esto depende totalmente de la implementación. ¡Nunca confíe en un detalle de implementación para la funcionalidad de su aplicación!

por lo que recomiendo no utilizar Marshal.AllocHGlobal(), malloc(), Marshal.FreeHGlobal() y free() transversal.

Un ejemplo, en el que te encontrarás con graves problemas es si usas una biblioteca, que hace una especie de magia de lujo malloc()/free() - incluso es posible que no lo sepas.

+1

No, ¡simplemente no funciona en absoluto! ¡No hay fuerza ni poder sobre eso! –

+0

@DavidHeffernan ¡Interesante! Teníamos esto en una aplicación y normalmente funcionaba bien en Mono, las cosas comenzaron a romperse con las bibliotecas de lujo, así que investigamos. –

+1

Eso suena como que en realidad no funcionó. Pero Mono puede ser una bestia diferente. Estoy asumiendo MS.neto y de ahí la finalidad de mi comentario. –

Cuestiones relacionadas