Está en la página 1de 6

4/3/2014

Programacin en C/Manejo dinmico de memoria - Wikilibros

Programacin en C Manejo dinmico de memoria


De Wikilibros, la coleccin de libros de texto de contenido libre. Programacin en C/Manejo dinmico de memoria Seguramente durante todo tu recorrido con este libro, especialmente en la seccin de punteros, te hablbamos sobre la asignacin dinmica de memoria. Como su nombre lo dice, este es una forma de conseguir espacio en memoria, dndote mas eficiencia y tcnicamente hacer lo que requieras hacer con este. En esta seccin haremos uso bastante (inevitablemente) de los punteros, por lo que te recomendamos que tengas muy bien establecidos estos conocimientos.

Contenido
1 Memoria dinmica 2 Memoria esttica 3 Diferencias, ventajas y desventajas 4 El lenguaje C y el manejo de la memoria 4.1 malloc 4.2 calloc 4.3 realloc 4.4 free 5 Buenas prcticas

Memoria dinmica
Es memoria que se reserva en tiempo de ejecucin. Su principal ventaja frente a la esttica, es que su tamao puede variar durante la ejecucin del programa. (En C, el programador es encargado de liberar esta memoria cuando no la utilice ms). El uso de memoria dinmica es necesario cuando a priori no conocemos el nmero de datos/elementos a tratar.

Memoria esttica
Es el espacio en memoria que se crea al declarar variables de cualquier tipo de dato (primitivas [int,char...] o derivados [struct,matrices,punteros...]). La memoria que estas variables ocupan no puede cambiarse durante la ejecucin y tampoco puede ser liberada manualmente.

Diferencias, ventajas y desventajas


La memoria reservada de forma dinmica suele estar alojada en el heap o almacenamiento libre, y la memoria esttica en el stack o pila (con excepcin de los objetos de duracin esttica, que se vern ms adelante, los cuales normalmente se colocan en una zona esttica de datos). La pila generalmente es una zona muy limitada.
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Manejo_din%C3%A1mico_de_memoria 1/6

4/3/2014

Programacin en C/Manejo dinmico de memoria - Wikilibros

El heap, en cambio, en principio podra estar limitado por la cantidad de memoria disponible durante la ejecucin del programa y el mximo de memoria que el sistema operativo permita direccionar a un proceso. La pila puede crecer de forma dinmica, pero esto depende del sistema operativo. En cualquier caso, lo nico que se puede asumir es que muy probablemente dispondremos de menor espacio en la pila que en el heap. Otra ventaja de la memoria dinmica es que se puede ir incrementando durante la ejecucin del programa. Esto permite, por ejemplo, trabajar con arreglos dinmicos. Aunque en C, a partir del estndar C99 se permite la creacin de arreglos cuyo tamao se determina en tiempo de ejecucin, no todos los compiladores implementan este estndar. Adems, se sigue teniendo la limitante de que su tamao no puede cambiar una vez que se especifica, cosa que s se puede lograr asignando memoria de forma dinmica. Una desventaja de la memoria dinmica es que es ms difcil de manejar. La memoria esttica tiene una duracin fija, que se reserva y libera de forma automtica. En contraste, la memoria dinmica se reserva de forma explcita y contina existiendo hasta que sea liberada, generalmente por parte del programador. La memoria dinmica puede afectar el rendimiento. Puesto que con la memoria esttica el tamao de las variables se conoce en tiempo de compilacin, esta informacin est incluida en el cdigo objeto generado, por lo cual el proceso es muy eficiente. Cuando se reserva memoria de manera dinmica, se tienen que llevar a cabo varias tareas, como buscar un bloque de memoria libre y almacenar la posicin y tamao de la memoria asignada, de manera que pueda ser liberada ms adelante. Todo esto representa una carga adicional, aunque esto depende de la implementacin y hay tcnicas para reducir su impacto.

El lenguaje C y el manejo de la memoria


Todos los objetos tienen un tiempo de vida, es decir, el tiempo durante el cual se garantiza que el objeto exista. En C, existen 3 tipos de duracin: esttica, automtica y asignada. Las variables globales y las variables locales declaradas con el especificador s t a t i ctienen duracin esttica. Se crean antes de que el programa inicie su ejecucin y se destruyen cuando el programa termina. Las variables locales no s t a t i ctienen duracin automtica. Se crean al entrar al bloque en el que fueron declaradas y se destruyen al salir de ese bloque. Duracin asignada se refiere a los objetos cuya memoria se reserva de forma dinmica. Como se explic anteriormente, esta memoria se crea y se debe liberar de forma explcita. Los arreglos de longitud variable de C99 son un caso especial. Tienen duracin automtica, con la particularidad de que son creados a partir de su declaracin. La biblioteca estndar de C proporciona las funciones m a l l o c ,c a l l o c ,r e a l l o cy f r e epara el manejo de memoria dinmica. Estas funciones estn definidas en el archivo de cabecera s t d l i b . h .

malloc
La funcin m a l l o creserva un bloque de memoria y devuelve un puntero void al inicio de la misma. Tiene la siguiente definicin:
v o i d* m a l l o c ( s i z e _ ts i z e ) ;

donde el parmetro s i z eespecifica el nmero de bytes a reservar. En caso de que no se pueda realizar la asignacin, devuelve el valor nulo (definido en la macro N U L L ), lo que permite saber si hubo errores en la asignacin de memoria. Ej:

http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Manejo_din%C3%A1mico_de_memoria

2/6

4/3/2014

Programacin en C/Manejo dinmico de memoria - Wikilibros

i n t* p u n t e r o ; c h a r* p u n t c a r c ; p u n t e r o = ( i n t* ) m a l l o c ( 4 ) ; p u n t c a r c = ( c h a r* ) m a l l o c ( 2 0 0 ) ;

A continuacin se muestra un ejemplo de su uso:

i n t* i ; / *R e s e r v a m o sl am e m o r i as u f i c i e n t ep a r aa l m a c e n a ru ni n tya s i g n a m o ss ud i r e c c i nai* / i=m a l l o c ( s i z e o f ( i n t ) ) ; / *V e r i f i c a m o sq u el aa s i g n a c i ns eh a y ar e a l i z a d oc o r r e c t a m e n t e* / i f( i = =N U L L ){ / *E r r o ra li n t e n t a rr e s e r v a rm e m o r i a* / }

Uno de los usos ms comunes de la memoria dinmica es la creacin de vectores cuyo nmero de elementos se define en tiempo de ejecucin:

i n t* v e c t 1 ,n ; p r i n t f ( " N m e r od ee l e m e n t o sd e lv e c t o r :" ) ; s c a n f ( " % d " ,& n ) ; / *R e s e r v a rm e m o r i ap a r aa l m a c e n a rne n t e r o s* / v e c t 1=m a l l o c ( n*s i z e o f ( i n t ) ) ; / *V e r i f i c a m o sq u el aa s i g n a c i ns eh a y ar e a l i z a d oc o r r e c t a m e n t e* / i f( v e c t 1 = =N U L L ){ / *E r r o ra li n t e n t a rr e s e r v a rm e m o r i a* / }

calloc
La funcin c a l l o cfunciona de modo similar a m a l l o c , pero adems de reservar memoria, inicializa a 0 la memoria reservada. Se usa comnmente para arreglos y matrices. Est definida de esta forma:
v o i d* c a l l o c ( s i z e _ tn m e m b ,s i z e _ ts i z e ) ;

El parmetro n m e m bindica el nmero de elementos a reservar, y s i z eel tamao de cada elemento. El ejemplo anterior se podra reescribir con calloc de esta forma:

i n t* v e c t 1 ,n ; p r i n t f ( " N m e r od ee l e m e n t o sd e lv e c t o r :" ) ; s c a n f ( " % d " ,& n ) ; / *R e s e r v a rm e m o r i ap a r aa l m a c e n a rne n t e r o s* /


http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Manejo_din%C3%A1mico_de_memoria 3/6

4/3/2014

Programacin en C/Manejo dinmico de memoria - Wikilibros

v e c t 1=c a l l o c ( n ,s i z e o f ( i n t ) ) ; / *V e r i f i c a m o sq u el aa s i g n a c i ns eh a y ar e a l i z a d oc o r r e c t a m e n t e* / i f( v e c t 1 = =N U L L ){ / *E r r o ra li n t e n t a rr e s e r v a rm e m o r i a* / }

realloc
La funcin realloc redimensiona el espacio asignado de forma dinmica anteriormente a un puntero. Tiene la siguiente definicin:
v o i d* r e a l l o c ( v o i d* p t r ,s i z e _ ts i z e ) ;

Donde p t res el puntero a redimensionar, y s i z eel nuevo tamao, en bytes, que tendr. Si el puntero que se le pasa tiene el valor nulo, esta funcin acta como m a l l o c . Si la reasignacin no se pudo hacer con xito, devuelve un puntero nulo, dejando intacto el puntero que se pasa por parmetro. Al usar r e a l l o c , se debera usar un puntero temporal. De lo contrario, podramos tener una fuga de memoria, si es que ocurriera un error en r e a l l o c . Ejemplo de r e a l l o cusando puntero temporal:

/ *R e s e r v a m o s5b y t e s* / v o i d* p t r=m a l l o c ( 5 ) ; / *R e d i m e n s i o n a m o se lp u n t e r o( a1 0b y t e s )yl oa s i g n a m o sau np u n t e r ot e m p o r a l* / v o i d* t m p _ p t r=r e a l l o c ( p t r ,1 0 ) ; i f( t m p _ p t r= =N U L L ){ / *E r r o r :t o m a rm e d i d a sn e c e s a r i a s* / } e l s e{ / *R e a s i g n a c i ne x i t o s a .A s i g n a rm e m o r i aap t r* / p t r=t m p _ p t r ; }

Cuando se redimension la memoria con r e a l l o c , si el nuevo tamao (parmetro s i z e ) es mayor que el anterior, se conservan todos los valores originales, quedando los bytes restantes sin inicializar. Si el nuevo tamao es menor, se conservan los valores de los primeros s i z ebytes. Los restantes tambin se dejan intactos, pero no son parte del bloque regresado por la funcin.

free
La funcin f r e esirve para liberar memoria que se asign dinmicamente. Si el puntero es nulo, f r e eno hace nada. Tiene la siguiente definicin:
v o i df r e e ( v o i d* p t r ) ;

El parmetro p t res el puntero a la memoria que se desea liberar:

i n t* i ;
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Manejo_din%C3%A1mico_de_memoria 4/6

4/3/2014

Programacin en C/Manejo dinmico de memoria - Wikilibros

i=m a l l o c ( s i z e o f ( i n t ) ) ; f r e e ( i ) ;

Una vez liberada la memoria, si se quiere volver a utilizar el puntero, primero se debe reservar nueva memoria con m a l l o co c a l l o c :

i n t* i=m a l l o c ( s i z e o f ( i n t ) ) ; f r e e ( i ) ; / *R e u t i l i z a m o si ,a h o r ap a r ar e s e r v a rm e m o r i ap a r ad o se n t e r o s* / i=m a l l o c ( 2*s i z e o f ( i n t ) ) ; / *V o l v e m o sal i b e r a rl am e m o r i ac u a n d oy an ol an e c e s i t a m o s* / f r e e ( i ) ;

Buenas prcticas
Como se vio en las secciones anteriores, siempre que se reserve memoria de forma dinmica con m a l l o c , r e a l l o co c a l l o c , se debe verificar que no haya habido errores (verificando que el puntero no sea N U L L ). Cuando se trata de verificar el valor de un puntero (y slo en ese caso), se puede usar de forma indistinta 0 N U L L . Usar uno u otro es cuestin de estilo. Como ya se vio, las funciones de asignacin dinmica de memoria devuelven un puntero v o i d . Las reglas de C establecen que un puntero v o i dse puede convertir automticamente a un puntero de cualquier otro tipo, por lo que no es necesario hacer una conversin (cast), como en el siguiente ejemplo:

/ *E lp u n t e r ov o i dd e v u e l t op o rm a l l o ce sc o n v e r t i d oe x p l c i t a m e n t eap u n t e r oi n t* / i n t* i=( i n t* ) m a l l o c ( s i z e o f ( i n t ) ) ;

Aunque no hay un consenso, muchos programadores prefieren omitir la conversin anterior porque la consideran menos segura. Si accidentalmente se olvida incluir el archivo s t d l i b . h(donde estn definidas m a l l o c ,c a l l o c ,r e a l l o cy f r e e ) en un programa que use dichas funciones, el comportamiento puede quedar indefinido. Si omitimos la conversin explcita, el compilador lanzar una advertencia. Si, en cambio, realizamos la conversin, el compilador generar el cdigo objeto de forma normal, ocultado el bug. Una posible razn para usar la conversin explcita es si se escribe cdigo en C que se vaya a compilar junto con cdigo C++, ya que en C++ s es necesario realizar esa conversin. En cualquier caso, dado que el manejo de memoria es un tema complejo, y ste es un error muy comn, se debe hacer nfasis en que cuando se trabaja con memoria dinmica, siempre se debe verificar que se incluya el archivo s t d l i b . h . Tratar de utilizar un puntero cuyo bloque de memoria ha sido liberado con f r e epuede ser sumamente peligroso. El comportamiento del programa queda indefinido: puede terminar de forma inesperada, sobrescribir otros datos y provocar problemas de seguridad. Liberar un puntero que ya ha sido liberado tambin es fuente de errores.
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Manejo_din%C3%A1mico_de_memoria 5/6

4/3/2014

Programacin en C/Manejo dinmico de memoria - Wikilibros

Para evitar estos problemas, se recomienda que despus de liberar un puntero siempre se establezca su valor a N U L L .

i n t* i ; i=m a l l o c ( s i z e o f ( i n t ) ) ; f r e e ( i ) ; i=N U L L ;

Obtenido de http://es.wikibooks.org/w/index.php? title=Programacin_en_C/Manejo_dinmico_de_memoria&oldid=220249 Esta pgina fue modificada por ltima vez el 16 feb 2014, a las 18:59. El texto est disponible bajo la Licencia Creative Commons Atribucin/Compartir-Igual 3.0; pueden aplicarse trminos adicionales. Vase Trminos de uso para ms detalles.

http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Manejo_din%C3%A1mico_de_memoria

6/6