Nombres y Asociaciones ¿Qué son Nombres y Asociaciones? . . . en el contexto de lenguajes de programación Lenguajes de Programación I Ernesto Hernández-Novich <[email protected]> mnemónica que denota un elemento de interés. Nombres y Asociaciones y el elemento que denota. • Creadas y destruidas • Logran la Abstracción – Copyright © 2007-2016 Lenguajes de Programación I • Relación entre un nombre • Cadena alfanumérica Universidad “Simón Bolívar” Hernández-Novich (USB) Asociación (Binding) Nombre (Name) Nombres y Asociación según las decisiones tomadas por el diseñador. objetivo de los lenguajes de programación. 2016 1 / 37 Hernández-Novich (USB) Momento de Asociación Lenguajes de Programación I Nombres y Asociaciones 2 / 37 2016 4 / 37 Momento de Asociación ¿Cuándo se asocia un nombre a “algo”? Las asociaciones más tempranas Binding Time Cuando el lenguaje sólo es una idea Momento de Asociación (Binding Time) 2016 Al momento de Diseñar el Lenguaje (Language Design Time) • Instante en que comienza la relación entre el nombre y lo denotado. • Momento preciso en que se establece e intervalo de duración • Palabras reservadas. dependen de la decisión de diseño. • Tipos primitivos y sus constructores. • Asociación temprana – mejorará la eficiencia de ejecución. • Asociación tardía – mejorará la flexibilidad de uso. Hernández-Novich (USB) Lenguajes de Programación I 2016 3 / 37 Hernández-Novich (USB) Lenguajes de Programación I Nombres y Asociaciones Momento de Asociación Nombres y Asociaciones Momento de Asociación Las asociaciones más tempranas Las asociaciones del usuario Cuando se construye la implantación Mientras se escribe el programa Al momento de Escribir el Programa (Program Writing Time) Al momento de Implantar el Lenguaje (Language Implementation Time) • El Programador es libre de escoger nombres para: • Tipos y sus constructores. • Variables. • Funciones o Procedimientos. • Módulos. • Precisión para representar elementos. • Disposición de elementos almacenados en memoria. • Acoplamiento con el subsistema de I/O. • Sin entrar en conflicto con lo decidido por Diseñador e Implantador. Hernández-Novich (USB) Lenguajes de Programación I Nombres y Asociaciones 2016 5 / 37 Hernández-Novich (USB) Momento de Asociación Lenguajes de Programación I Nombres y Asociaciones Las asociaciones de construcción Mientras se produce el programa ejecutable Mientras se completa el programa ejecutable • Asociar construcciones de Alto Nivel con equivalentes de Bajo Nivel. • ¿Cuáles instrucciones de máquina para cada fragmento de programa? • ¿Cuáles ubicaciones de máquina para datos estáticos? • Generación de nombres internos. • Para puntos de salto en el lenguaje de máquina. • Para identificar datos constantes. • Para agregar información de debugging o profiling. Hernández-Novich (USB) Lenguajes de Programación I 2016 7 / 37 6 / 37 2016 8 / 37 Momento de Asociación Las asociaciones de transformación Al momento de Compilar el Programa (Compile Time) 2016 Al momento de Enlazar el Programa (Link Time) • Resolver referencias entre módulos y librerías. • Decidir la distribución final de memoria. Hernández-Novich (USB) Lenguajes de Programación I Nombres y Asociaciones Momento de Asociación Nombres y Asociaciones Momento de Asociación Las asociaciones de arranque Mientras se ejecuta el programa Ready. . . set. . . . . . go! Al momento de Ejecutar el Programa (Run Time) Al momento de Cargar el Programa (Load Time) • Asociar valores a variables. • Asignación de memoria virtual. • Aparecen, cambian, desaparecen y reaparecen – • Asignación de recursos adicionales. dependen del flujo de ejecución y anidamiento. • Ejecutar funciones y procedimientos. Hernández-Novich (USB) Lenguajes de Programación I Nombres y Asociaciones 2016 9 / 37 Hernández-Novich (USB) Estático vs. Dinámico Lenguajes de Programación I Nombres y Asociaciones Estático vs. Dinámico 2016 10 / 37 2016 12 / 37 Estático vs. Dinámico El panorama de las cosas Más temprano que tarde, ma non troppo Momentos de Asociación Temprana Asociación Temprana • También llamada Asociación Estática (Static Binding). • Apunta hacia la eficiencia. • Típica de los lenguajes compilados. Momentos de Asociación Tardía • Diseño. • Enlace. • Implantación. • Carga. • Escritura. • Ejecución. • Compilación. Asociación Tardía • Enlace. • También llamada Asociación Dinámica (Dynamic Binding). La frontera entre lo estático y dinámico es bastante difusa en algunos lenguajes. • Apunta hacia la flexibilidad. • Típica de los lenguajes interpretados. Hernández-Novich (USB) Lenguajes de Programación I 2016 11 / 37 Hernández-Novich (USB) Lenguajes de Programación I Nombres vs. Objetos Ciclo de Vida Nombres vs. Objetos Diferentes tiempos, diferentes espacios Espacio Vital ¿Dónde se almacenan los objetos? Memoria virtual asignada al programa en ejecución MAXADDR • Creación de Objetos – • Sistema de Operación variables, tipos, procedimientos. . . “cosas” del lenguaje. • Creación de Asociaciones entre Nombres y Objetos. asigna espacio virtual al proceso. • Uso de los Objetos a través de esas Asociaciones. • MAXADDR según CPU – • Activación y reactivación de Asociaciones suspendidas temporalmente. 4Gb en 32 bits puro, 64Gb en 32 bits PAE, 16Eb en 64 bits puro. • Destrucción de Asociaciones entre Nombres y Objetos. • Destrucción de Objetos. • Programa sólo puede El tiempo que pasa entre la creación y destrucción de una Asociación se denomina Tiempo de Vida (lifetime). usar lo asociado. 0 Hernández-Novich (USB) Lenguajes de Programación I Nombres vs. Objetos 2016 13 / 37 Hernández-Novich (USB) Espacio Vital Lenguajes de Programación I Nombres vs. Objetos Mecanismos de Asignación de Almacenamiento 2016 14 / 37 2016 16 / 37 Espacio Vital Guía para la existencia El Tiempo de Vida establece el Espacio #include <stdio.h> #include <stdlib.h> • Objetos Estáticos • Ubicación fija absoluta. • Establecida a tiempo de compilación o carga. • Mantenida durante la ejecución del programa. • Objetos en Pila • Almacenados y removidos en la Pila de Ejecución. • Modelan la invocación de subrutinas o bloques anidados. • Objetos en Heap • Almacenados y removidos arbitrariamente. • Implícita o explícitamente en conexión con variables dinámicas. Hernández-Novich (USB) Lenguajes de Programación I 2016 int foo = 21; int baz(int qux) { int *bar; bar = (int *) malloc(sizeof(int)); *bar = foo * qux; return *bar; } main() { printf("The answer is %d\n", baz(2)); } 15 / 37 Hernández-Novich (USB) Lenguajes de Programación I Nombres vs. Objetos Almacenamiento Estático Nombres vs. Objetos Almacenamiento Estático Almacenamiento Estático ¿Cuáles son los objetos estáticos? El código al principio, las globales después Almacenamiento Estático MAXADDR • Código ejecutable – en general, no puede modificarse. • Tamaño fijo – • Variables globales. calculado al compilar. • Constantes – explícitas e implícitas. • TEXT sólo puede • Variables locales que preservan su valor entre invocaciones. ejecutarse. • Tablas de Símbolos para debugging y profiling. • DATA/BSS puede tener DATA/BSS • En lenguajes sin recursión, el espacio para subrutinas. datos sin inicializar. TEXT 0 Hernández-Novich (USB) Lenguajes de Programación I Nombres vs. Objetos 2016 17 / 37 Hernández-Novich (USB) Almacenamiento Estático Lenguajes de Programación I Nombres vs. Objetos Guía para la existencia – Objetos Estáticos 2016 18 / 37 Almacenamiento en Pila Almacenamiento en Pila ¿Cuáles objetos aparecen y desaparecen según el flujo? #include <stdio.h> #include <stdlib.h> • En lenguajes con recursión, cada subrutina cuenta con su espacio de trabajo denominado Registro de Activación para almacenar • Argumentos. • Variables locales. • Direcciones y valores de retorno. int foo = 21 ; int baz (int qux) { int *bar; bar = (int *) malloc(sizeof(int)); *bar = foo * qux; • El programa ejecutable debe mantener la pila: • El llamador sigue la secuencia de invocación antes de saltar. • El llamado debe comenzar con un prólogo y finalizar con un epílogo para el mantenimiento. return *bar; • Una pila modela la aparición de llamadas a rutinas activas – } main () { printf( "The answer is %d\n" } Hernández-Novich (USB) no sabemos cuántas, ni en cuál orden, hasta correr el programa. . . , baz(2)); Lenguajes de Programación I Los detalles (¡muchos!) los estudiaremos más adelante, ahora solamente interesa la idea general. 2016 19 / 37 Hernández-Novich (USB) Lenguajes de Programación I 2016 20 / 37 Nombres vs. Objetos Almacenamiento en Pila Nombres vs. Objetos Almacenamiento en Pila Almacenamiento en Pila Guía para la existencia – Objetos en Pila Pila de Ejecución #include <stdio.h> #include <stdlib.h> MAXADDR STACK int foo = 21 ; • Pila crece hacia las direcciones bajas. int baz (int qux ) { • Tamaño limitado por el int * bar ; bar = (int *) malloc(sizeof(int)); *bar = foo * qux; sistema de operación. • Usar instrucciones especiales del CPU (PUSH, POP) siempre que sea posible. DATA/BSS return *bar; } main () { printf( "The answer is %d\n" } TEXT 0 Hernández-Novich (USB) Lenguajes de Programación I Nombres vs. Objetos 2016 21 / 37 Hernández-Novich (USB) Almacenamiento en Pila , baz(2)); Lenguajes de Programación I Nombres vs. Objetos 2016 22 / 37 Almacenamiento en Pila Registro de Activación – Stack Frame Registro de Activación – Stack Frame Separación de preocupaciones Separación de preocupaciones El código generado para la llamada. . . • Comienza por empilar parámetros y saltar a la rutina – esta es la secuencia de llamada en el llamador. El código generado para la rutina. . . • Establece un apuntador base a la pila (frame o base pointer). • Accede a los objetos en la pila usando desplazamientos relativos (offset) en relación al frame pointer. • No importa dónde quede el registro de activación en la pila, pues los desplazamientos son relativos al “centro” de cada invocación. • El prólogo dentro del procedimiento llamado • Conserva el frame pointer previo. • Establece valor concreto para frame pointer. • Mueve tope de la pila para reservar espacio local. • El procedimiento llamado ejecuta. • El epílogo dentro del procedimiento llamado • Regresa tope de pila al frame pointer. • Restablece el frame pointer anterior. • Retorna al llamador. Todo el código es generado estáticamente, para controlar llamadas que ocurrirán dinámicamente. Hernández-Novich (USB) Lenguajes de Programación I 2016 23 / 37 Hernández-Novich (USB) Lenguajes de Programación I 2016 24 / 37 Nombres vs. Objetos Almacenamiento en Pila Nombres vs. Objetos Almacenamiento en Pila Registro de Activación Guía para la existencia – Las llamadas . . . el rastro de la ejecución Llamando a baz(2) #include <stdio.h> #include <stdlib.h> ← SP • SP (Stack Pointer) – • main empila el 2 tope de la pila. locales int foo = 21 ; • BP (Base Pointer) – Sub D ← BP • Locales – tienen offset negativo. Sub C int * bar ; bar = (int *) malloc(sizeof(int)); *bar = foo * qux; • Argumentos – tienen Sub A Hernández-Novich (USB) Lenguajes de Programación I Nombres vs. Objetos • baz mueve SP main () { printf( "The answer is %d\n" } ¿quién llamó a quién? MAXADDR 2016 25 / 37 • baz empila BP. apunta al “centro”. } • Cadena dinámica – CPU guarda la dirección en pila. • baz copia SP a BP, return *bar; offset positivo. Sub B • main llama a baz – int baz (int qux ) { base de stack frame. argumentos • BP → main. Hernández-Novich (USB) Almacenamiento en Pila , baz(2)); haciendo espacio para bar. Lenguajes de Programación I Nombres vs. Objetos 2016 Almacenamiento en Pila Guía para la existencia – Las llamadas Guía para la existencia – Las llamadas En el cuerpo de la subrutina baz(2) Regresando de la subrutina baz(2) #include <stdio.h> #include <stdlib.h> #include <stdio.h> #include <stdlib.h> • BP más offset positivo para qux. int foo = 21 ; negativo para bar. int baz (int qux ) { int * bar ; bar = (int *) malloc(sizeof(int)); *bar = foo * qux; return *bar; main () { printf( "The answer is %d\n" } Hernández-Novich (USB) podria tener offset positivo o estar en un registro. } main () { printf( "The answer is %d\n" } Hernández-Novich (USB) • baz retorna a main. valor de retorno del tope de la pila o de un registro. return *bar; 27 / 37 BP anterior. • main recupera el *bar = foo * qux; , baz(2)); 2016 • baz desempila el int * bar ; bar = (int *) malloc(sizeof(int)); llamar a malloc. Lenguajes de Programación I hasta BP liberando el espacio de bar. int baz (int qux ) { • El valor de retorno • Proceso similar para } • baz mueve SP int foo = 21 ; • BP más offset 26 / 37 , baz(2)); Lenguajes de Programación I 2016 28 / 37 Nombres vs. Objetos Almacenamiento en Heap Nombres vs. Objetos Almacenamiento en Heap Almacenamiento en Heap ¿Cuáles objetos aparecen y desaparecen arbitrariamente? Completa Almacenamiento en Heap MAXADDR • Heap – región de almacenamiento en la cual pueden reservarse y STACK liberarse bloques arbitrariamente. • Crece hacia las • Primitivas o funciones del lenguaje para reservar y liberar bloques. • El ejecutable debe contar con código adicional que implante la direcciones altas. • Crece en bloques estrategia de manejo de memoria: HEAP • Lista de Bloques Libres (Free List). • Política para reservar bloques: • First Fit. • Best Fit. necesario reciclar. Lenguajes de Programación I Nombres vs. Objetos 2016 TEXT 0 29 / 37 Hernández-Novich (USB) Almacenamiento en Heap Lenguajes de Programación I Nombres vs. Objetos Guía para la existencia – Almacenamiento en Heap Fragmentación del Heap . . . no lo puedo colorear / Memoria libre que no puedes usar #include <stdio.h> #include <stdlib.h> 2016 30 / 37 Almacenamiento en Heap • malloc reserva espacio en el heap para un int. int foo = 21 ; Fragmentación Interna • bar apunta a ese int baz (int qux ) { int * bar ; bar = (int *) malloc(sizeof(int)); *bar = foo * qux; return *bar; } main () { printf( "The answer is %d\n" } Hernández-Novich (USB) • Nunca se reduce – DATA/BSS Escribir un manejador de memoria es un ejercicio complicado que se estudia en Lenguajes de Programación III Hernández-Novich (USB) grandes – se amplía con sbrk en Unix. espacio. • El objeto contenido no ocupa todo el bloque asignado. • El heap tendrá bastante más espacio reservado, disponible para otros malloc. • El espacio sobrante no puede utilizarse. • Aparece cuando el tamaño de los bloques es fijo o no hay disponible ningún bloque que ajuste mejor. , baz(2)); Lenguajes de Programación I 2016 31 / 37 Hernández-Novich (USB) Lenguajes de Programación I 2016 32 / 37 Nombres vs. Objetos Almacenamiento en Heap Nombres vs. Objetos Almacenamiento en Heap Fragmentación del Heap ¿Cuánto cuesta almacenar en el Heap? Memoria libre que no puedes usar Eficiencia en espacio y tiempo • Recorrer la Lista Libre es proporcional a su longitud. • Varias Listas Libres cada una con bloques de tamaño diferente. • Sistema de “panitas” (Buddy System). • Sistema Fibonacci. • Combinación de contigüos en ambos casos. Fragmentación Externa • El objeto es más grande que cualquiera de los bloques disponibles. • Hay muchos bloques pequeños que no son continuos, o bien son • Compactar el heap a intervalos regulares puede reducir la continuos pero no se consolidaron. Hernández-Novich (USB) Lenguajes de Programación I Nombres vs. Objetos fragmentación externa. 2016 33 / 37 Hernández-Novich (USB) Almacenamiento en Heap Lenguajes de Programación I Nombres vs. Objetos Liberación de Espacio en el Heap 2016 34 / 37 Almacenamiento en Heap Disposición de almacenamiento Fallas accediendo a memoria • Explícita. • Simple de implantar con alguna instrucción primitiva en el lenguaje. • Es el método más eficiente. • Requiere que el programador identifique correctamente el momento en que el objeto debe destruirse... • ...pero suelen equivocarse y ocurren errores por referencias colgantes o pérdida de memoria. • Implícita. • Conocida como recolección de basura (garbage collection). • Complejo de implantar para minimizar el impacto sobre el tiempo de ejecución y los requerimientos de memoria disponible. • El programador no necesita hacer nada. • Prácticamente obligatorio en lenguajes interpretados y muy frecuente en lenguajes con Máquina Virtual. Hernández-Novich (USB) Lenguajes de Programación I 2016 35 / 37 MAXADDR STACK Your fault! HEAP DATA/BSS Segmentation fault El programa accede a una dirección dentro de su espacio, pero sin asociación. TEXT 0 Hernández-Novich (USB) Lenguajes de Programación I 2016 36 / 37 Referencias Bibliográficas Bibliografía • [Scott] • Secciones 3.1 y 3.2. • Ejercicios y Exploraciones • Página de Wikipedia sobre Memory Management • Página de Wikipedia sobre Segmentation Fault • Compile el programa sólo hasta lenguaje ensamblable y fíjese en la asignación de espacio hecha por el compilador, así como en la secuencia de llamada. Hernández-Novich (USB) Lenguajes de Programación I 2016 37 / 37