Bueno, ahora que conocemos el concepto de montón y sus ventajas, vamos a ver con qué funciones podemos manejar los montones.
Vamos allá:
Creación del montón
La creación de cualquier montón (ya sea el montón por defecto o cualquier otro) se realiza a través de la función HeapCreate:
HANDLE HeapCreate(
DWORD flOpciones,
banderas de reserva
DWORD dwTamañoInicial, tamaño inicial del montón
DWORD dwTamañoMaximo );
máximo tamaño del montón
Esta función crea un montón de un tamaño especificado y nos retorna un descriptor (handle) para acceder a él posteriormente.
Vamos a ver para qué sirve cada parámetro:
- flOpciones: Es posible indicar cualquier combinación de las siguientes banderas:
- HEAP_GENERATE_EXCEPTIONS: cuando cualquier función de manejo de montones falle al acceder a este montón, se generará una excepción del sistema, en vez de retornar NULL. Las posibles excepciones son STATUS_ACCESS_VIOLATION y STATUS_NO_MEMORY.
- HEAP_NO_SERIALIZE: desactiva el acceso sincronizado al montón. El gestor de montones utiliza un sistema de sincronización de hilos para asegurarse de que los datos son siempre consistentes cuando varios hilos acceden simultáneamente a un mismo montón. Este sistema ralentiza algo las operaciones de reserva y liberación en el montón, por lo que podemos desactivar esta sincronización sólo en las siguientes situaciones:
- Si el proceso sólo va a tener un hilo.
- Si el proceso tiene más de un hilo pero sólo uno de ellos accede al montón
- Si el proceso tiene más de un hilo y varios acceden al montón, pero se gestiona el acceso sincronizado manualmente.
- HEAP_ZERO_MEMORY: indica que después de todas las asignaciones de memoria realizadas en este montón, se inicializará el contenido con ceros.
- HEAP_GROWABLE (indocumentado): Indica el montón puede crecer automáticamente cuando su espacio se agote. Para configurar este comportamiento, se debe pasar un 0 en el parámetro dwTamañoMaximo, en vez de emplear esta bandera, que es privada del sistema.
- HEAP_REALLOC_INPLACE_ONY (indocumentado): indica que cualquier reasignación de memoria de este montón (a través de la función HeapReAlloc) se hará sin mover los bloques de su situación actual.
- HEAP_DISABLE_COALESCE_ON_FREE (indocumentado): Cuando se libera un bloque del motón, automáticamente el gestor intenta refundir bloques libres que estén adyacentes a este, para así crear un bloque más grande y evitar fragmentación. Esta bandera desactiva este comportamiento, lo cual acelera la ejecución.
- HEAP_CREATE_ALIGN_16 (indocumentado): Crea los bloques del montón con una alineación de 16 bytes.
- HEAP_FREE_CHECKING_ENABLED: indocumentado y desconocido.
- HEAP_CREATE_ENABLE_TRACING: indocumentado y desconocido.
- HEAP_TAIL_CHECKING_ENABLED: indocumentado y desconocido.
- HEAP_MAXIMUM_TAG: indocumentado y desconocido.
- HEAP_PSEUDO_TAG_FLAG: indocumentado y desconocido.
- HEAP_TAG_SHIFT: indocumentado y desconocido.
- dwTamañoInicial: indica el tamaño (en bytes) que inicialmente contará con compromiso físico (más adelante veremos que el montón se almacena en el sistema de memoria virtual, por lo que cumple las mismas normas que cualquier otro bloque reservado con VirtualAlloc). Este tamaño podrá ser todo lo grande que queramos (con la limitación física de la máquina) y se redondeará al tamaño de página inmediatamente superior. Cuanto mayor sea este valor, más tardará la función en realizar la creación del montón.
- dwTamañoMaximo: indica el tamaño máximo (en bytes) que podrá albergar el montón. Además, indica el tamaño del bloque que se reservará (pero no comprometerá) al crear el montón.
Si en este parámetro se especifica el valor 0, el espacio reservado inicialmente en el montón será el mismo que el indicado en dwTamañoInicial, sin embargo, este crecerá conforme vaya necesitando más espacio, hasta que el gestor de memoria virtual no cuente con más recursos.
Si hemos especificado un tamaño máximo (dwTamañoMaximo > 0), contamos con una pequeña limitación: no podemos reservar bloques de memoria en el montón mayores a 524.280 bytes. Esta limitación no existe si el montón es auto-extensible (dwTamañoMaximo = 0).
Si la función tiene éxito, se devuelve un descriptor (handle) del montón, que será utilizado en sucesivas llamadas.
Si ocurre algún error la función retornará nulo o lanzará una excepción del sistema, si se indicó la bandera HEAP_GENERATE_EXCEPTIONS.