40
MEMORIA DINAMICA

Memoria dinamica

Embed Size (px)

Citation preview

MEMORIA DINAMICA

INTRODUCCION

DATOS EN MEMORIA

Datos estáticos: Su tamaño y forma es constante durante la ejecución de un programa y por tanto se determinan en tiempo de compilación. El ejemplo típico son los arrays. Tienen el problema de que hay que dimensionar la estructura de antemano, lo que puede conllevar desperdicio o falta de memoria. Datos dinámicos: Su tamaño y forma es variable (o puede serlo) a lo largo de un programa, por lo que se crean y destruyen en tiempo de ejecución. Esto permite dimensionar la estructura de datos de una forma precisa: se va asignando memoria en tiempo de ejecución según se va necesitando.

ASPECTOS A CONSIDERAR PARA EL USO DE MEMORIA DINAMICA

• En muchas ocasiones no es posible conocer de antemano la cantidad de variables necesarias para un programa computacional.

• Existen aplicaciones que requieren de enormes cantidades de arreglos o datos por momentos breves en el funcionamiento del mismo, por lo que no es viable declarar de antemano a estas como variables, globales o locales de una función. Lo anterior implica emplear funciones de ANSI C que permiten reservar memoria de manera dinámica y ampliarla, reducirla o destruirla en tiempo de ejecución.

• El manejo de memoria dinámica es la base del poder del lenguaje C, C++ y le da la capacidad de crear programas complejos que emplean grandes cantidades de memoria y los maneja de manera eficiente.

Memoria dinámica

Es memoria que se reserva en tiempo de ejecución. Su principal ventaja frente a la estática, es que su tamaño puede variar durante la ejecución del programa. (En C, el programador es encargado de liberar esta memoria cuando no la utilice más). El uso de memoria dinámica es necesario cuando a priori no conocemos el número de datos/elementos a tratar.

Cuando el sistema operativo carga un programa para ejecutarlo y lo convierte en proceso, le asigna cuatro partes lógicas en memoria principal: texto, datos (estáticos), pila y una zona libre. Esta zona libre (o heap) es la que va a contener los datos dinámicos, la cual, a su vez, en cada instante de la ejecución tendrá partes asignadas a los mismos y partes libres que fragmentaran esta zona, siendo posible que se agote si no se liberan las partes utilizadas ya inservibles. (La pila también varia su tamaño dinámicamente, pero la gestiona el sistema operativo, no el programador):

• Las variables globales y del programa principal (main) se almacenan en posiciones fijas de la memoria llamada memoria de datos.

• Las variables locales se almacenan en el segmento de memoria llamada pila y existen solo cuando se hace una invocación a la función que las declaro. También se pueden declarar variables estáticas locales que también se almacenan en segmentos fijos de memoria o en la memoria de datos , sin embargo, también están disponibles en la función que las declaro.

• Todas estas variables comparten una característica en común, se definen cuando se compila el programa. Esto significa que el compilador reserva espacio en memoria para almacenar los valores para estas variables.

• Sin embargo, no todas las veces es posible conocer el numero de variables con el que va a constar nuestro programa. C C++ ofrece al desarrollador la opción de crear diferentes tipos de variables de forma dinámica, para crear tales variables se utilizan funciones como: malloc(), realloc(), calloc(), y free().

MEMORIA DINAMICA

• Las regiones de memoria que reservan/liberan estas funciones son almacenadas en el montículo o heap.

MEMORIA DINAMICA

• Por lo regular cuando se diseña un algoritmo, se debe conocer que elementos de entrada tendrá y cual será la salida, sin embargo, en algunas ocasiones no se sabe de forma exacta el numero de variables que requerirá nuestro algoritmo.

• Por ejemplo, suponga que se van a registrar el numero de calificaciones de un conjunto de alumnos, para resolver este problema se podría utilizar una arreglo de calificaciones, sin embargo, si el numero de alumnos crece, nuestro programa ya no seria valido, puesto que no existen los recursos necesarios para almacenar todos los datos validos.

Para resolver este problema es necesario recurrir al uso de apuntadores y a la asignación dinámica de memoria.

ASIGNACION DINAMICA DE MEMORIA

ASIGNACION DINAMICA DE MEMORIA

El espacio de memoria asignado a una variable generada de manera dinámica se crea durante la ejecución del programa (tiempo de ejecución), al contrario de las variables declaradas en código, que el espacio de memoria se les asigna en tiempo de compilación.

Una variable que es generada dinámicamente, se construye (por ejemplo con malloc)y se puede destruir en tiempo de ejecución (uso de free).

Stdlib.h

Malloc()

IMPORTANTE

Veamos un ejemplo en el cual el usuario ingresa una cantidad variable de números por consola. Primero el sistema le pide que especifiqué la cantidad de números que va a ingresar, y luego de ingresados, los imprime, incrementando en 1 cada número.

#include <stdio.h>#include <stdlib.h>int leercantidad();void leer(int, int *);void imprimir(int, int *);main(){ int cantidad,*ptr; cantidad=leercantidad(); ptr=(int *)malloc(cantidad*sizeof(int));//reservo bloques de memoria leer(cantidad,ptr); imprimir(cantidad,ptr);}

int leercantidad(){ int n; printf("Cuantos datos quiere ingresar:\t"); scanf("%d",&n); return n;}void leer(int n, int *ptr){ for(int i=0;i<n;i++) { printf("dato [%d]\t",i+1); //scanf("%d",&ptr[i]); /*scanf("%d",ptr) ptr++;*/ Mueve el puntero usando la aritmetica scanf("%d",(ptr+i));//Mueve el puntero referenciado }}void imprimir(int n, int *ptr){ for(int i=0;i<n;i++) { printf("dato [%d] %d\n",i+1,*(ptr+i)); // ptr++;

}}

ARREGLOS DINAMICOS

Crear un programa que lea una línea de caracteres, reserva memoria para un buffer de tantos caracteres como leídos y se copia en el buffer la cadena ingresada:

Ejemplo

Crear un programa que cree un array de N valores de tipo entero de forma dinámica

Ejemplo: Vector de tamaño dinámico

#include <stdio.h> #include <stdlib.h>

float media (float v[], int n){ int i; float suma = 0;

for (i=0; i<n; i++) suma += v[i];

return suma/n;}main(){ int i; int n; float *v; printf("Número de elementos del vector: "); scanf("%d",&n); // Creación del vector v = malloc(n*sizeof(float)); // Manejo del vector for (i=0; i<n; i++) v[i] = i; printf("Media = %f\n", media(v,n)); // Liberación de memoria free(v);}

MATRICES DINAMICAS

Matrices Dinámicas

Realice un programa que genere una matriz de n filas y n columnas, muestre el resultado utilizando el formato de array y el de puntero:

Practica UTILIZANDO MEMORIA DINAMICA REALICE EL SIGUIETE EJERCICIOMENU1 DIAGONAL PRINCIPAL2 DIAGONAL SECUNDARIA3 COMBINAR DIAGONALES4 SALIR

CREAR LAS FUNCIONESLLENARDIAGONAL_PRINCIPALDIAGONAL_SECUNDARIACOMBINAR_DPDS

MALLOC vs CALLOC- void *malloc(size_t size);- void *calloc(size_t nmemb, size_t size);

malloc() Con esta función obtenemos el puntero que nos da la dirección del bloque de memoria reservado dinámicamente. Sin embargo, malloc() no inicializa el contenido de este bloque de memoria.

calloc() Cumple la misma función que malloc(), con una diferencia: calloc() si inicializa a 0 el contenido de cada elemento del array dinámico.

Se puede apreciar como en la definición de calloc() el primer parámetro es el nº de elementos y a continuación el tamaño del elemento (por ejemplo para int: sizeof(int)). Mientras que en malloc() debíamos pasarle el tamaño del bloque entero, es decir: "nºelementos*tamaño de elemento".

Esta función posee una gran utilidad, pues es la que nos sirve para redimensionar nuestro bloque de memoria (array, etc) generado dinámicamente.

Sus parámetros son: el puntero a redimensionar y el nuevo tamaño, que al igual que en malloc() será: "nº elementos*tamaño de elemento".

Esta función guarda el contenido que tengamos almacenado en el bloque de memoria a redimensionar.

En el caso de que lo hagamos mas pequeño elimina el contenido sobrante. En caso de que al redimensionar no exista espacio consecutivo para el nuevo bloque realloc() cambia de lugar nuestro bloque y nos devuelve el puntero a la nueva dirección. Es por esto por lo que siempre deberemos guardar el puntero obtenido con esta función. 

void *realloc(void *p, size_t size) realloc cambia el tamaño del objeto al que apunta p y lo hace de tamaño size. El contenido de la memoria no cambiará en las posiciones ya ocupadas. Si el nuevo tamaño es mayor que el antiguo, no se inicializan a ningún valor las nuevas posiciones. En el caso en que no hubiese suficiente memoria para “realojar” al nuevo puntero, se devuelve NULL y p no varía. El puntero que se pasa como argumento ha de ser NULL o bien un puntero devuelto por malloc(), calloc() o realloc().

#define N 10#include <stdio.h>main(){char c, *cambiante;int i;i=0;cambiante = NULL;printf("\nIntroduce una frase. Terminada en [ENTER]\n");while ((c=getchar()) != '\n') { if (i % N == 0){ printf("\nLlego a %d posiciones y pido hasta %d", i, i+N); cambiante=(char *)realloc((char *)cambiante,(i+N)*sizeof(char)); if (cambiante == NULL) exit(-1); } /* Ya existe suficiente memoria para el siguiente carácter*/ cambiante[i++] = c;}

REALLOC