Aunque tengamos varios montones adicionales, el más importante es el montón por defecto. Esto es porque, internamente, cualquier reserva de memoria utilizando funciones del lenguaje como malloc, calloc, etc., se hace en el montón por defecto.
Siendo prácticos podemos decir que el siguiente bloque de código:
{
void *buffer;
buffer = malloc( 1024 );
// aquí se hace lo que sea
free( buffer );
}
Es equivalente a este otro código:
{
void *buffer;
buffer = ::HeapAlloc( GetProcessHeap(), 0, 1024 );
// aquí se hace lo que sea
::HeapFree( ::GetProcessHeap(), 0, buffer );
}
Además, cualquier reserva que haga el sistema para un proceso, también la hace en el montón por defecto. Por ejemplo, cuando hacemos una llamada a la función FindFirstFile, el sistema creará una pequeña zona de memoria para su uso interno, en el montón por defecto del proceso llamante. Esa zona de memoria se liberará con otra función, en nuestro caso con FindClose.
Debido a esto, es muy importante que los accesos al montón por defecto se hagan sincronizados, sin utilizar la bandera HEAP_NO_SERIALIZE, ya que existirán múltiples hilos que accedan a él.
Este montón, tiene un tamaño por defecto de 1 MB, de los cuales tan sólo de comprometen 4 KB.
La configuración de este parámetro depende del entorno en el que trabajemos, por poner algún ejemplo:
 |
Visual C++ a través de la opción del enlazador /HEAP:reservar[,comprometer]
|
 |
C++Builder 6 desde la opción de menú Project - Options - Linker - PE File Options. En esta sección vemos, tanto la configuración del almacenamiento de la pila, como del montón por defecto:

Los campos MinHeapSize y MaxHeapSize indican el espacio a reservar y comprometer respectivamente. |
Cuando explicamos el parámetro dwTamañoMaximo de la función HeapCreate, dijimos que si contenía un valor mayor que 0, el montón no podría crecer automaticamente. Esto se falso para el montón por defecto, ya que éste sí podrá crecer aunque se haya definido un tamaño máximo. De hecho, el montón por defecto crece en segmentos de 1 MB cada vez que necesita memoria.
La gente de Microsoft recomienda que el tamaño máximo sea lo suficientemente grande como para que no se llegue a una situación en que el montón por defecto deba crecer. Para ello debemos definir un tamaño máximo en el que quepan todos los objetos que vamos a crear dinámicamente durante la ejecución.
El tamaño mínimo nos indica cuánto será comprometido al crear el montón, por lo que si indicamos un tamaño muy grande, la carga de la aplicación se ralentizará (pero durante la ejecución, las reservas serán más rápidas).
Supongamos que nuestra aplicación va a manejar una lista enlazada (o un objeto TList, CList, etc.). Cada elemento de esta lista será un puntero de 32 bits, que apuntará a una estructura creada dinámicamente. Cada una de las estructuras ocupará 234 bytes, que aplicando el alineado de campos pasará a ocupar 256 bytes. Si hacemos una estimación, y decimos que en el caso más desfavorable tendremos en memoria 10.000 estructuras, aplicamos la siguiente ecuación:
dwTamañoMaximo = (256 + 32) * 10.000 ) = 2.880.000 bytes = 2812,5 KB
En nuestro ejemplo, y para curarnos en salud, yo definiría un tamaño máximo para el montón de 3 MB.
Para calcular el tamaño mínimo, podemos hacer una estimación de la ocupación que se hará del montón durante el arranque (los objetos que van a estar en memoria durante toda la vida de la aplicación).
Si suponemos que de la lista anterior, tan sólo 1000 van a estar en memoria continuamente, entonces aplicamos la siguiente fórmula:
dwTamañoMinimo = (256 + 32) * 1.000) = 288.000 = 281,25 KB
Yo utilizaría un tamaño mínimo de 300 KB, para asegurarnos que el montón tendrá memoria comprometida inicial para albergar todos los objetos que se cargan en el arranque.
Este (junto con el tamaño de pila), puede ser un buen método para optimizar el tiempo de carga de una aplicación.