Solución al Koan #2
¿HAY VIDA DESPUES DE LA MUERTE?
Me costó trabajo comprender cómo era posible que la llamada a Free no diera problemas. Mi primera reacción fue pensar que alguna de las variantes presentadas en el problema tenía problemas de perdida de memoria (memory leaks). En consecuencia, dediqué casi una hora a comprobar esto. Y no: no encontré problema alguno. Entonces, desde el fondo de mi inconsciente comenzó a aflorar la solución: un método de los formularios que había visto hacía mucho tiempo, me había llamado la atención y lo había archivado en el sótano. Fui al código fuente a confirmarlo y, efectivamente, la clave estaba en el injustamente olvidado método Release.
¿Qué hace el famoso método Release? Poca cosa: deposita en la cola de mensajes de la aplicación un mensaje definido por Delphi, denominado CM_RELEASE. Lo importante es que el mensaje se envía con la función PostMessage del API de Windows, no con la más común SendMessage. Esto quiere decir que el mensaje no se trata inmediatamente por el procedimiento de ventana (windows procedure) del formulario. El tratamiento ocurre asíncronamente, en el próximo paso del bucle de mensajes.
¿Y qué hace la ventana cuando recibe un CM_RELEASE? Bueno, para decirlo con suavidad, se suicida. Es decir, llama a Free. ¿Por qué Delphi necesita un método tan sádico y perverso para liquidar a un pobre formulario? Suponga, con un poco de imaginación, que el siguiente diagrama representa al bucle de mensajes, y al recorrido por las rutinas del programa que se produce durante el procesamiento de determinado mensaje. Suponga también que en el nodo señalado, el formulario que está tratando el mensaje decide poner fin a sus días, llamando a Release. Bueno, colega, no es tan sencillo abandonar este mundo. Puede que todavía tengas que hacer algo algunos nodos más abajo, pero lo más frecuente es que tengas que realizar trámites burocráticos durante el camino de regreso al bucle de mensajes.
Está claro entonces que cuando asignamos caFree en el parámetro del evento OnClose, Delphi lo que hace es llamar a Release, en vez de Free, que es lo que casi todos esperamos. Normalmente, la destrucción de formulario se efectúa en el próximo paso del bucle de mensajes. Pero si nos adelantamos y destruimos la ventana antes de que llegue su momento, no pasa nada. Sencillamente, el comando CM_RELEASE (la carta-bomba) nunca alcanza su destino. Y esto es normal en Windows.
|