En lenguajes como C o C++, el programador es responsable de reservar y liberar la memoria del montículo. En C, esto se realiza mediante las funciones malloc() y free(). En C++, los operadores new y delete se usan esencialmente con el mismo significado; se implementan mediante malloc() y free(), por lo que la siguiente discusión se restringirá a éstas.
Cada bloque de memoria reservado con malloc() debería, con el tiempo, devolverse al conjunto de memoria disponible mediante exactamente una llamada a free(). Es importante llamar a free() en el momento adecuado. Si se olvida la dirección de un bloque pero no se llama a free() para esa dirección, la memoria del bloque queda inutilizable hasta la terminación del programa. Esto se denomina pérdida de memoria. Por otra parte, si un programa llama a free() para un bloque de memoria y sigue utilizando la memoria, crea un conflicto de utilización con subsiguientes usos de malloc() que juzguen disponible para nuevas reservas el mismo bloque de memoria. Esto se denomina uso de memoria libre. Tiene las mismas graves consecuencias que hacer referencia a datos no inicializados: finalizaciones no deseadas del programa, resultados inesperados y casques misteriosos.
Una causa común de pérdida de memoria son los recorridos poco comunes del código. Por ejemplo, una función puede reservar un bloque de memoria, hacer unos cálculos y liberarla. Puede que un cambio de requisitos añada una comprobación en los cálculos que detecte una condición de error que fuerce la salida prematura de la función. Es fácil olvidarse de liberar el bloque de memoria si se toma esta salida prematura, especialmente si se añade mucho después. Estas pérdidas suelen pasar inadvertidas mucho tiempo. El error sólo se da en un pequeño número de llamadas y las máquinas modernas suelen tener grandes cantidades de memoria virtual, por lo que la pérdida sólo se hace evidente en un proceso largo que utilice la función con pérdidas frecuentemente. Por ello, es importante evitar las pérdidas mediante una convención del código o una estrategia que minimice este tipo de errores.
Como Python hace un uso intensivo de malloc() y free(), necesita una estrategia para evitar las pérdidas de memoria y el uso de memoria liberada. El método utilizado se denomina saldo de referencias. El principio es simple: cada objeto contiene un contador, que se incrementa cada vez que se almacena una referencia al objeto en cualquier parte y se decrementa cada vez que se borra la referencia. Cuando el saldo del contador es cero, significa que se ha borrado la última referencia al objeto, por lo que se puede liberar su memoria.
Una estrategia alternativa se denomina recolección automática de basura (a veces, el saldo de referencias se considera también una estrategia de recolección de basura, de ahí el uso de ``automática'' para distinguirlas). La gran ventaja de la recolección automática de basura es que no es necesario que el usuario llame a free() explícitamente (se dice que hay una mejora de velocidad o uso de memoria, pero no hay datos concluyentes). La desventaja es que para C no existe ningún recolector automático de basura auténticamente transportable, mientras que el saldo de referencias se puede implementar transportablemente (siempre que estén disponibles las funciones malloc() y free(), lo que garantiza el estándar de C). Quizás algún día se haga disponible algún recolector automático de basura para C. Hasta entonces, habrá que vivir contando referencias.