Asignatura: Algoritmos y estructuras de datos Nombres: Yaró Flores Tellez Hanssel Carcache Aguilar Kevin Estrada Loaisiga Fecha: 15 / 02 / 2019 Introducción El presente documento tiene como finalidad dar a conocer el concepto de general de gestión de memoria, asi como sus carcaterísticas, tipos y ejemplos aplicados; no obstante, para definir que es la gestión de memoria debemos tener en claro que es la memoria y cuales son sus funciones. La memoria de una computadora almacena los datos de entrada, programas que se han de ejecutar y resultados. En la mayoría de las computadoras existen dos tipos de memoria principal: memoria de acceso aleatorio RAM que soporta almacenamiento temporal de programas y datos y memoria de sólo lectura ROM que almacena datos o programas de modo permanente. (Luis Joyanes A. 2008, p. 9). A como Joyanes señala existen dos tipos de memoria principal (RAM Y ROM), ahora bien podemos definir a la memoria RAM como la memoria se utiliza para almacenar, de modo temporal información, datos y programas. En general, la información almacenada en memoria puede ser de dos tipos: las instrucciones de un programa y los datos con los que operan las instrucciones; mientras que, la memoria ROM es una memoria que almacena información de modo permanente en la que no se puede escribir (viene pregrabada “grabada” por el fabricante) ya que es una memoria de sólo lectura. La memoria principal es la encargada de almacenar los programas y datos que se están ejecutando y su principal característica es que el acceso a los datos o instrucciones desde esta memoria es muy rápido (Aguilar, 2008). ¿Qué es la gestión de la memoria? Según Y. Gutierrez (2013), se denomina gestión de memoria al acto de gestionar la memoria de un dispositivo informático. De forma simplificada se trata de proveer mecanismos para asignar secciones de memoria a los programas que las solicitan, y a la vez, liberar las secciones de memoria que ya no se utilizan para que estén disponibles para otros programas. Vikas Awasthy, (2015) “La gestión de memoria requiere que el programador proporcione formas de asignar dinámicamente partes de la memoria a los programas, cuando se solicite, y liberarla para reutilizarla cuando ya no sea necesaria. En cualquier sistema informático avanzado, donde más de un proceso puede estar ejecutándose en un momento dado, esto es crítico.” La memoria es uno de los principales recursos de la computadora, la cual debe de administrarse con mucho cuidado. Aunque actualmente la mayoría de los sistemas de cómputo cuentan con una alta capacidad de memoria, de igual manera las aplicaciones actuales tienen también altos requerimientos de memoria, lo que sigue generando escasez de memoria en los sistemas multitarea y/o multiusuario. Al hablar de gestión de memoria existen dos tipos datos y se corresponden con el tipo de memoria, ya sea dinámica (DRA) o estática (SRAM) TIPO VENTAJAS DESVENTAJAS Menor capacidad, debido a que cada celda de La velocidad de acceso almacenamiento requiere es alta. más transistores. Para retener los datos Mayor costo por bit. solo necesita estar Memoria energizada. estática Son más fáciles de No se puede modificar el tamaño de la estructura en T.D.E diseñar. No es optima con grandes Logica simple cantidades de datos Optimas para resolver Desperdicios de memoria problemas cuando no se utiliza totalidad del tamaño TIPO VENTAJAS Mayor Memoria dinámica densidad DESVENTAJAS y capacidad. consumo bajar. Necesita recargar de la Menor costo por bit. Menor La velocidad de acceso es de potencia. Gestión de memoria en C Hay dos formas en que la memoria se puede asignar en C: información. almacenada para retenerla. Diseño complejo. Declarando variables Al solicitar explícitamente espacio desde C El lenguaje de programación C proporciona varias funciones para la asignación y administración de memoria. Estas funciones se pueden encontrar en el archivo de cabecera <stdlib.h>. Todas las funciones se dan a continuación: void * calloc (int num, int size): esta función asigna una matriz de elementos num. El tamaño de cada elemento en bytes será el tamaño. void free (void * address): esta función libera un bloque de memoria especificado por una dirección. void * malloc (int num): esta función asigna una matriz de bytes numéricos y los deja inicializados. void * realloc (void * address, int newsize): esta función reasigna la memoria y la amplía a un nuevo tamaño. Importancia de la gestión de memoria. Considerando que una computadora solo tiene una cantidad finita de memoria, es natural que las aplicaciones deban administrar esta memoria de manera conservadora. Brain y Crawford (S.F.) “Para comprender mejor la importancia de la administración de la memoria, considere cómo un programa usa la memoria. Cuando ejecuta un programa por primera vez, se carga en la memoria de su computadora y comienza a ejecutarse enviando y recibiendo instrucciones del procesador de la computadora. Cuando el programa necesita ejecutar una función particular, carga esa función en otra parte de la memoria mientras dura su ejecución, y luego abandona esa memoria cuando la función está completa. Además, cada nuevo dato utilizado en el programa principal ocupa memoria durante la duración del programa.” Una de las cosas que hace que C sea un lenguaje tan versátil es que el programador puede escalar un programa para ejecutarlo con una cantidad muy pequeña de memoria. Cuando se escribió C por primera vez, esta era una característica importante porque las computadoras no eran tan poderosas como lo son hoy. Con la demanda actual de productos electrónicos pequeños, desde teléfonos móviles hasta pequeños dispositivos médicos, existe un interés renovado en mantener los requisitos de memoria pequeños para algunos programas. C es el lenguaje de referencia para la mayoría de los programadores que necesitan mucho control sobre el uso de la memoria. Ejemplos de gestión de memoria en C. Ejemplo 1: El principal problema es que las variables estáticas tienen un tamaño fijo. En C++ se permite reservar y liberar zonas de memoria a la hora de ejecutar un programa. Para la reserva de memoria se usa la función new junto con el tipo de variable que queremos reservar por ejemplo: New int; New float; New char; Esto se aplica de esta forma: Float *ptr; ptr = new float; Otra de forma de gestionar la memoria es creando un arreglo siguiendo el mismo ejemplo anterior: New tipo[num]; De esta forma se reserva espacio para num posiciones del tipo de variable que se desea ocupar. Esto se aplica de esta forma: Int *ptr; Ptr = new int[15]; Lo que hace esto es que se creen 15 espacios del tipo int en la memoria donde podemos asignar los valores que deseamos. Ejemplo 2: Cout<<”Numero de valores?”; Cin<<tam; Int *ptr = new int [tam]; For (int i=0; i<tam; i++) Ptr[i] = i; En este ejemplo podemos ver que nos pide de cuantos valores queremos crear el espacio de memoria para poder almacenar el número de valores que deseemos. Para liberar un espacio de memoria se utiliza la función delete, esto se puede ocupar de la siguiente manera: Delete puntero; Delete [] puntero; Por ejemplo: Ptr[4]=17; Cout<<ptr[4]; Delete[] ptr; Cout <<ptr[4]; La primera que mandemos a mostrar el puntero se mostrará 17, pero una vez que el delete libere el espacio de memoria que utiliza en el segundo cout se mostrará un error porque dicho valor ya no existe. Ejemplos de gestión de memoria en C. Asignando memoria dinámicamente. Durante la programación, si somos conscientes del tamaño de una matriz, es fácil definir la matriz. Por ejemplo, para almacenar el nombre de cualquier persona, si la matriz puede tener un máximo de 100 caracteres, podemos definir algo de la siguiente manera: char name [100]; Pero ahora, consideremos una situación en la que no tenemos idea de la longitud del texto que necesitamos almacenar. Por ejemplo, si queremos almacenar una descripción detallada sobre un tema, debemos definir un puntero a un carácter sin definir cuánta memoria se requiere y luego, según el requisito, podemos asignar memoria, como se muestra en el siguiente ejemplo. : #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char name[100]; char * description; strcpy(name, “Vikas Awasthy”); /* allocate memory dynamically * / description = malloc( 200 * sizeof(char) ); if( description == NULL ) { fprintf(stderr, “Error - unable to allocate required memory \n”); } else { strcpy( description, “Vikas Awasthy is an Application Developer”); } printf(“Name = %s\n”, name ); printf(“Description: %s\n”, description ); } Output of Code:Name = Vikas Awasthy Description: Vikas Awasthy is an Application Developer Redimensionando y liberando memoria Cuando se ejecuta nuestro programa, el sistema operativo libera automáticamente toda la memoria asignada por nuestro programa, pero como buena práctica, cuando ya no necesitamos más memoria, debemos liberar esa memoria llamando a la función free (). Alternativamente, podemos aumentar o disminuir el tamaño de un bloque de memoria asignado llamando a la función realloc (). Revisemos el programa anterior una vez más y hagamos uso de las funciones realloc () y free (): #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char name[100]; char * description; strcpy(name, “Vikas Awasthy”); /* allocate memory dynamically * / description = malloc( 30 * sizeof(char) ); if( description == NULL ) { fprintf(stderr, “Error - unable to allocate required memory\n”); } else { strcpy( description, “Vikas Awasthy is an Application Developer.”); } /* suppose we want to store more description * / description = realloc( description, 100 * sizeof(char) ); if( description == NULL ) { fprintf(stderr, “Error - unable to allocate required memory\n”); } else { strcat( description, “He works in IBM India.”); } printf(“Name = %s\n”, name ); printf(“Description: %s\n”, description ); /* release memory using free() function * / free(description); } Output of above code:Name = Vikas Awasthy Description: Vikas Awasthy is an Application Developer. He works in IBM India. Conclusiones La gestión de la memoria puede ser muy útil para resolver aspectos como la presencia simultánea de más de un programa en memoria, la carga de programas y su ubicación, la ejecución de programas que no caben completos en memoria y la gestión eficiente del espacio de memoria libre. Si se trabaja solo con variables estáticas y no se gestiona bien la memoria nos podemos encontrar con varios problemas como insuficiencia de memoria debido a que estas variables tienen un tamaño fijo y también la situación donde no se pueden complementar varios programas en un mismo código. Recomendaciones El buen uso de la gestión de memoria es muy importante para cualquier sistema informático debido a que todos cuentan con una memoria finita que si llega a saturarse puede ser crítico para el sistema. Aunque los sistemas de hoy en día cuenten con más memoria para evitar que se sature, los programas de hoy también ocupan mucho más memoria que antes lo que genera escasez de memoria. Por lo que se recomienda utilizar cada vez más la memoria dinámica para emplear lo necesario para el programa y de esta forma no malgastar la memoria, es necesario utilizarla y liberarla una vez que se haya dejado de utilizar para así evitar que el sistema se vea perjudicado gravemente. Esto no indica que se tenga que utilizar la memoria dinámica para todo tipo de programa pero si se recomienda que la estática sea ocupada para pequeñas cantidades de datos, y al contrario la memoria dinámica tiene que ser utilizada para grandes cantidades de datos, de esta forma se puede evitar el mal uso de la memoria. Acontinuación se brindaran reglas que forman parte del CERT C Coding Standard proveido por el Instituto de Ingeniería de software, SEI por sus siglas en ingles. Regla 08. Gestión de Memoria. No acceder a la memoria liberada. Liberar la memoria asignada dinámicamente cuando ya no sea necesaria. Asignar y copiar estructuras que contienen un miembro de matriz flexible dinámicamente. Solo memoria libre asignada dinámicamente. Asignar memoria suficiente para un objeto. No modifique la alineación de objetos llamando a realloc (). Para conocer mas acercar del SEI CERT C Coding Standard visite el siguiente enlace: https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-c-codingstandard-2016-v01.pdf Bibliografia Joyanes Aguilar, L. (2008). Fundamentos de programación: algoritmos, estructuras de datos y objetos (4ta. Ed.). España: McGRAW-HILL. Gutiérrez Sánchez Y. (14 de Abril de 2013). Sistemas Operativos: Gestion de memoria. Recuperado de https://sites.google.com/site/sisoper1/home/gestion-de-memoria Vikas Awasthy, (9 de Diciembre de 2015). The Importance of Memory Management. Recuperado de https://opensourceforu.com/2015/12/the-importance-of-memorymanagement/ Anonimo, (S.F.). Elementos de programación: Memoria dinámica. Recuperado de http://www.lcc.uma.es/~fvn/EleProg/punteros_apuntes_y_ejercicios.pdf Diego, (3 de Abril de 2011). Estructura de datos: Memoria dinámica y estatica. Recuperado de http://diego-estructuradedatos1.blogspot.com/2011/04/memoria-estatica-y- dinamica.html Brain, M. y Crawford, S. (S.F.). How C programming works: The importance of memory management in C. Recuperado de https://computer.howstuffworks.com/cprogramming11.htm Salvador Pozo, (Septiembre del 2000). Operadores de memoria new y delete. Recuperado de http://c.conclase.net/curso/?cap=013b Repositorio. Universidad del Pais Vasco, (S.F.). Sistemas Operativos II: Gestión de la memoria. Recuperado de http://www.sc.ehu.es/acwlaroa/SO2/Apuntes/Cap4.pdf Repositorio. Universitat Jaume I, (S.F.). Gestión dinámica de memoria. Recuperado de http://repositori.uji.es/xmlui/bitstream/handle/10234/119887/tema6.pdf;jsessioni d=A00F329211612B469417FB5BAA89DC2C?sequence=1 Carnegie Mellon University, (S.F.). SEI CERT C Coding Standard: Rule 08. Memory Management (MEM). Recuperado de https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152142