Un programa de Windows siempre tiene al menos dos montones en el que se asigna memoria no administrada. Primero está el montón de procesos predeterminado, utilizado por Windows cuando necesita asignar memoria en nombre del programa. El segundo es un montón utilizado por la infraestructura COM para asignar. El .NET P/Invoke Marshaller supone que este montón fue utilizado por cualquier código no administrado cuya firma de función requiera la desasignación de memoria.
AllocHGlobal asigna desde el montón de procesos, AllocCoTaskMem asigna desde el montón COM.
Cuando escribe código de interoperabilidad no administrado, siempre debe evitar una situación en la que el código que asigna memoria no administrada no sea el mismo que el código que lo libera. Habría una buena posibilidad de que se use el desasignador equivocado. Esto es especialmente cierto para cualquier código que interopera con un programa C/C++. Dichos programas tienen su propio asignador que usa su propio montón, creado por el CRT al inicio. Desasignar tal memoria en otro código es imposible, no puede obtener de manera confiable el manejador de pila. Esta es una fuente muy común de problemas de P/Invoke, especialmente porque la función HeapFree() en XP y versiones anteriores ignoran silenciosamente solicitudes para liberar memoria que no estaba asignada en el montón correcto (filtrando la memoria asignada) pero Vista y Win7 bloquean el programa con una excepción
No hay necesidad de preocuparse por esto en su caso, las funciones de mmsystem API que está utilizando están limpias. Fueron diseñados para asegurar que el mismo código que asigna también desasigne. Esta es una razón por la que tiene que llamar waveInPrepareHeader(), que asigna buffers con el mismo código que en última instancia les desasigna. Probablemente con el montón de proceso predeterminado.
sólo es necesario para alojar la estructura WAVEHDR. Y usted es responsable de liberarlo cuando haya terminado con él. Las API de mmsystem no lo hacen por usted, sobre todo porque no pueden hacerlo de manera confiable. Por lo tanto, puede usar cualquiera de los dos asignadores, solo necesita asegurarse de llamar al método gratuito correspondiente. Todas las API de Windows funcionan de esta manera. Yo uso CoTaskMemAlloc() pero realmente no hay una preferencia. Solo que si estoy llamando al código mal diseñado, es ligeramente más probable usar el montón COM.
Nunca debe usar sizeof() en un escenario de interoperabilidad. Devuelve el tamaño gestionado del tipo de valor. Puede que no sea lo mismo después de que el intérprete de comandos P/Invoke haya traducido un tipo de estructura de acuerdo con las directivas [StructLayout] y [MarshalAs]. Solo Marshal.SizeOf() te da un valor correcto garantizado.
ACTUALIZACIÓN: hubo un gran cambio en VS2012. La biblioteca de tiempo de ejecución de C que se incluye ahora asigna desde el montón de proceso predeterminado en lugar de usar su propio montón. A largo plazo, eso hace que AllocHGlobal sea la vía más probable para el éxito.
¿Hay alguna diferencia de rendimiento entre las dos funciones de asignación? – DxCK
'AllocCoTaskMem' es más eficiente. 'AllocHGlobal' llama' LocalAlloc', que tiene la siguiente nota: "Las funciones locales tienen una sobrecarga mayor y proporcionan menos características que otras funciones de administración de memoria". Ver https://msdn.microsoft.com/en-us/library/windows/desktop/aa366723(v=vs.85).aspx – IamIC