Universidad de Costa Rica | Escuela de Ingeniería Eléctrica IE-0117 Programación Bajo Plataformas Abiertas Memoria dinámica 1. Asignación de memoria en un programa Existen dos formas básicas de asignar memoria para un programa. La asignación de memoria estática define la cantidad de memoria que se utilizará en tiempo de compilación y no durante la ejecución del programa. Este es el tipo de asignación estándar usado en C cuando se crean variables y arreglos regulares. La asignación de memoria estática es muy eficiente y consume pocos recursos. Sin embargo, es poco flexible, sobretodo cuando un programa debe manejar datos de tamaño variable. Por otro lado, la asignación de memoria dinámica permite que un programa pueda reservar nueva memoria, de tamaño variable, en cualquier momento de la ejecución de un programa. El programa debe hacer una solicitud al sistema operativo. Si hay suficiente memoria disponible el sistema operativo asignará la memoria y le retornará al programa un puntero que hace referencia al inicio del sector reservado. 2. Solicitud de nueva memoria La solicitud de nueva memoria se hace usando las funciones malloc() o calloc(). Ambas funciones difieren únicamente en la forma en que se especifica la cantidad de memoria. malloc() recibe como argumento un número entero que indica la cantidad de bytes que se desea reservar. calloc() recibe dos argumentos: la cantidad de elementos que se almacenaran en el sector de memoria solicitado y el tamaño de cada uno de ellos. Ambas funciones retornan un puntero genérico (void *) que apunta al inicio del sector de memoria reservado, o bien el puntero NULL en caso de que no se pueda hacer la asignación. int *a, *b; a = (int *)malloc(20 * sizeof(int)); b = (int *)calloc(20, sizeof(int)); En el ejemplo se asignan dos porciones de memoria del mismo tamaño, cada una con capacidad para almacenar 20 números enteros. Nótese como es necesario hacer un casting para convertir el puntero genérico retornado por las funciones al tipo correcto. Debido a que se utiliza un puntero para manejar la porción de memoria dinámica, puede usarse aritmética de punteros, o bien el operador [] para acceder a cada posición: int i; for(i = 0; i < 20; i++) { a[i] = i; } 1 IE-0117 Programación Bajo Plataformas Abiertas 3. Memoria dinámica Cambio del tamaño de un sector de memoria dinámica Es posible cambiar el tamaño de un sector de memoria reservado dinamicamente en cualquier momento, usando la función realloc(): a = (int *)realloc((void *)a, 50 * sizeof(int)); En el ejemplo se cambia el tamaño del área de memoria a la que hace referencia a para que pueda almacenar 50 enteros. Si se el tamaño original es menor que el nuevo tamaño, simplemente se agregará más espacio al final. Si el nuevo tamaño es menor, se truncará el sector de memoria y se perderán los últimos elementos. El cambio de tamaño de la memoria puede ser ineficiente en ocasiones, debido a que no siempre hay sufiente memoria contigua y es necesario copiar los datos a otras posiciones con más espacio. Por esta razón debe evitarse efectuar esta operación. 4. Liberación de memoria Algunos lenguajes de alto nivel como Java y Python utilizan memoria dinámica para almacenar la mayoría de las variables de un programa. Por esta razón, estos lenguajes implementan componentes, conocidos generalmente como recolectores de basura que liberan automáticamente la memoria cuando no se necesita más. El lenguaje C no cuenta con herramientas de este tipo, por lo que es necesario liberar la memoria manualmente. Es de suma importancia llevar a cabo esta tarea en el momento adecuado para evitar fugas de memoria que puedan afectar el desempeño de la aplicación y del sistema en general. Para liberar memoria debe usarse la función free(): free(a); 2