Memória Dinâmica
Introdução
Imagina que queremos receber uma string do utilizador e a seguir copiar essa mesma string para outras, para fazermos algumas alterações sem alterar a string original. Uns dos passos lógicos é declarar 2 strings com tamanho suficiente para poder guardar a nossa string.Mas com isso levanta se uma questão. Não vamos desperdiçar memória se a string previamente reservada não fosse totalmente ocupada? As repostas está na memória dinâmica. A memória dinâmica permite-nos alocar bytes em memória em qualquer parte do nosso programa, assim possibilitando que nos já saibamos quantos bytes de memória essa string vai ocupar para assim não desperdiçarmos memória.
Nota: Todas as funções descritas aqui tem o prototipo disponível no header stdlib.h
.
malloc
Aloca o número de bytes indicado pelo programador. A função retorna void *
o que quiser dizer que pode alocar elementos para todos os tipos de dados, em caso de erro devolve NULL.
void *malloc(size_t n_Bytes)
Onde:
size_t
: significa unsigned intn_Bytes
: é o número de bytes que queremos alocar em memória
#include<stdio.h>
#include<string.h>
#include<stdlib.h> /* Precisamos desta biblioteca para acessar as funçoes de alocaçao de memoria*/
int main(void)
{
char s[1000];
char *ptr; /* Precisamos de um ponteiros */
printf("Introduza a sua string:"); fgets(s,1000,stdin);
if((ptr = malloc (strlen(s)+1))==NULL) /* Alocaçao do novo vector de caracteres */
{
printf("Nao foi possivel alocar a memoria");
exit(1);
}
strcpy(ptr,s); /* Copia a string que o utilizador inseriu para a nova */
/* Vamos testar se correu todo bem */
printf("String do utilizador:%s",s);
printf("Nova String:%s",ptr);
free(ptr); /* Liberta a memoria */
return 0;
}
Explicação: Basicamente o programa recebe uma string, e depois criamos uma nova string, mas agora com o número exacto de bytes que a string necessita para assim não haver desperdício de memória.
calloc
Aloca o número indicado pelo programador, onde o tipo também é passado como parâmetro. Ainda inicializa os novos espaços de memória a 0
. A função devolve NULL
em caso de erro.
void *calloc(size_t num, size_t size)
Onde:
size_t
: significa unsigned intnum
: número de elementos que queremos criarsize
: tamanho de cada elemento
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char x;
char *ptr;
ptr = calloc (10,sizeof(char)); /* Alocaçao de 10 espaços de memoria do tipo char */
if(ptr==NULL)
{
printf("Erro na Alocaçao!\n");
exit(1);
}
free (ptr);
return 0;
}
realloc
Esta função basicamente altera o espaço que foi atribuído à partida. A função retorna NULL
em caso de erro.
void *realloc(void *ptr, size_t new_size)
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main(void)
{
char *ptr;
ptr = malloc(10)
char *temp;
temp = realloc(ptr, 1000); /* Se o realloc funcionou,
** temp aponta para uma área com 1000 bytes
** e o valor de ptr não é relevante.
* Se o realloc não funcionou
** temp aponta para NULL
** e ptr aponta para a área original, que pode ser libertada */
if (temp != NULL) {
ptr = temp;
}
/* Resto do código */
free(ptr);
return 0;
}
Nota: guardar o endereço da nova área no ponteiro que tem o endereço da área antiga.
ptr = realloc(ptr, 1000);
Dá origem, em caso de erro do malloc()
, a que se perca a referência ao bloco original e consequentemente haja uma "memory leak" no programa.
free
Normalmente quando um programa termina a sua execução toda a memória gasta nesse programa é libertada, mas é bom habito de programação sermos nós a libertar essa memória. A função free()
serve para isso mesmo.
void free(void *ptr)
free(ptr); /* ptr neste caso é o ponteiro para aquilo que criaram */