Você está na página 1de 28

Alocação dinâmica de

memória
Alocação dinâmica de memória

 Declarações alocam espaço na memória para as


variáveis;
 A quantidade de memória a alocar só se torna
conhecida durante a execução do programa;
 A alocação dinâmica é administrada pelas funções
malloc, realloc e free (biblioteca stdlib);
 #include <stdlib.h>
Alocação dinâmica de memória

A função malloc
 malloc (o nome é uma abreviatura de memory allocation)
aloca espaço para um bloco de bytes consecutivos na
memória RAM (= random access memory) do computador e
devolve o endereço desse bloco;
O número de bytes é especificado no argumento da função:

char *ptr;
ptr = malloc (1);
scanf ("%c", ptr);
Alocação dinâmica de memória

A função malloc

A transformação do ponteiro genérico em ponteiro-


para-char é automática; não é necessário escrever
ptr = (char *) malloc (1);.
O endereço é armazenado no ponteiro ptr, que é do
tipo ponteiro-para-char
Alocação dinâmica de memória

 A fim de alocar espaço para um objeto que


precisa de mais que 1 byte, convém usar o
operador sizeof, que diz quantos bytes o objeto
em questão tem:
typedef struct {
int dia, mes, ano;
} data;
data *d;
d = malloc (sizeof (data));
d->dia = 31; d->mes = 12; d->ano = 2019;
Alocação dinâmica de memória

 O sizeof não é uma função mas um operador, tal como


return, por exemplo;
 Os parênteses na expressão sizeof (data) são necessários
porque data é um tipo-de-dados (os parênteses são
análogos aos do casting);
 O operador sizeof também pode ser aplicado diretamente
a uma variável: se var é uma variável então sizeof var é
o número de bytes ocupado por var.
 Poderíamos ter escrito d = malloc (sizeof *d) no exemplo
acima.
Alocação dinâmica de memória

1-Escreva uma função que receba um


byte c (que pode representar um
caractere ASCII, por exemplo) e
transforme-o em uma string, ou seja,
devolva uma string de comprimento 1
tendo c como único elemento.
Alocação dinâmica de memória

2-Discuta, passo a passo, o efeito do


seguinte fragmento de código:
int *v;
v = malloc (10 * sizeof (int));
Alocação dinâmica de memória

3-Discuta o efeito do seguinte fragmento


de código:
x = malloc (10 * sizeof *x);
Alocação dinâmica de memória
A função free
variáveis alocadas estaticamente dentro
de uma função, também conhecidas
como variáveis automáticas ou locais,
desaparecem assim que a execução da
função termina.
Alocação dinâmica de memória
A função free
variáveis alocadas dinamicamente
continuam a existir mesmo depois que a
execução da função termina. Se for
necessário liberar a memória ocupada
por essas variáveis, é preciso recorrer à
função free.
free desaloca a porção de memória
alocada por malloc.
Alocação dinâmica de memória

A instrução free (ptr) avisa ao sistema que


o bloco de bytes apontado por ptr está
disponível para reciclagem. A próxima
invocação de malloc poderá tomar posse
desses bytes.
 Não aplique a função free a uma parte de
um bloco de bytes alocado por malloc (ou
realloc). Aplique free apenas ao bloco
todo.
Alocação dinâmica de memória

 O que há de errado com o seguinte fragmento de


código?
int *v;
v = malloc (100 * sizeof (int));
v[0] = 999;
free (v+1);
Alocação dinâmica de memória

A seguinte função promete devolver


um vetor com os 3 primeiros números
primos maiores que 1000. Onde está o
erro?
Alocação dinâmica de memória
 Um vetor (= array) com n elementos inteiros pode ser
alocado (e depois desalocado) durante a execução de um
programa:

int *v;
int n;
scanf ("%d", &n);
v = malloc (n * sizeof (int));
for (int i = 0; i < n; ++i)
scanf ("%d", &v[i]);
...
free (v);
Alocação dinâmica de memória

v = malloc (100 * sizeof


(int));
int v[100];
Qual diferença?
Alocação dinâmica de memória
 Matrizes bidimensionais são implementadas como vetores
de vetores. Uma matriz com m linhas e n colunas é um
vetor de m elementos cada um dos quais é um vetor de n
elementos. O seguinte fragmento de código faz a alocação
dinâmica de uma tal matriz:
int **M;
M = malloc (m * sizeof (int *));
for (int i = 0; i < m; ++i)
M[i] = malloc (n * sizeof (int));
 Portanto, M[i][j] é o elemento de M que está no
cruzamento da linha i com a coluna j.
Alocação dinâmica de memória

4- Escreva uma função que


desaloque a matriz M alocada
acima. Quais devem ser os
parâmetros da função?
Alocação dinâmica de memória

Redimensionamento e a função realloc


 Às vezes é necessário alterar, durante a execução do
programa, o tamanho de um bloco de bytes que foi
alocado por malloc. Isso acontece, por exemplo, durante
a leitura de um arquivo que se revela maior que o
esperado.
 Nesse caso, podemos recorrer à função realloc para
redimensionar o bloco de bytes.
Alocação dinâmica de memória

 A função realloc recebe o endereço de um bloco


previamente alocado por malloc (ou por realloc) e o
número de bytes que o bloco redimensionado deve ter. A
função aloca o novo bloco, copia para ele o conteúdo do
bloco original, e devolve o endereço do novo bloco.
 Se o novo bloco for uma extensão do bloco original, seu
endereço é o mesmo do original (e o conteúdo do original
não precisa ser copiado para o novo). Caso contrário,
realloc copia o conteúdo do bloco original para o novo e
libera o bloco original (invocando free). A propósito, o
tamanho do novo bloco pode ser menor que o do bloco
original.
Alocação dinâmica de memória

 Suponha, por exemplo, que alocamos um vetor de 1000 inteiros e


depois decidimos que precisamos de duas vezes mais espaço. Veja um
caso concreto:

int *v;
v = malloc (1000 * sizeof (int));
for (int i = 0; i < 990; i++)
scanf ("%d", &v[i]);
v = realloc (v, 2000 * sizeof (int));
for (int i = 990; i < 2000; i++)
scanf ("%d", &v[i]);
Alocação dinâmica de memória

 Nesse exemplo, poderíamos usar a seguinte


implementação ad hoc de realloc:

int *realloc (int *v, unsigned int N) {


int *novo = malloc (N);
for (int i = 0; i < 1000; i++)
novo[i] = v[i];
free (v);
return novo;
}
Alocação dinâmica de memória

5-Suponha dado um arquivo de texto que contém


uma sequência de números inteiros. O comprimento
da sequência é desconhecido. Escreva uma função
que imprima esses números em ordem inversa
(o último, depois o penúltimo, etc.). É claro que
você terá que ler todos os números e armazená-los
na memória. A dificuldade está em alocar espaço
para uma quantidade de números que só será
conhecida quando chegarmos ao fim do arquivo.
Alocação dinâmica de memória

 Se a memória do computador já estiver toda ocupada,


malloc não consegue alocar mais espaço e devolve NULL.
Convém verificar essa possibilidade antes de prosseguir:

ptr = malloc (sizeof (data));


if (ptr == NULL) {
printf ("Socorro! malloc devolveu NULL!\n");
exit (EXIT_FAILURE);
}
Alocação dinâmica de memória

 A digitação frequente e repetida desse teste é cansativa. Por isso, usaremos,


neste sítio, a seguinte função-embalagem (= wrapper function) de malloc:

void *mallocc (size_t nbytes) {


void *ptr;
ptr = malloc (nbytes);
if (ptr == NULL) {
printf ("Socorro! malloc devolveu NULL!\n");
exit (EXIT_FAILURE);
}
return ptr;
}
Alocação dinâmica de memória

 O parâmetro de mallocc é do tipo size_t (abreviatura de


size data type); em muitos computadores, size_t é o
mesmo que unsigned int.

 Da mesma forma, podemos preparar uma função-


embalagem reallocc para cuidar das situações em que
realloc devolve NULL.
Alocação dinâmica de memória

6 -É verdade que não convém alocar blocos de poucos bytes,


ou seja, invocar malloc com argumento muito pequeno?
7-Posso alocar um vetor estaticamente com número não-
constante de elementos? Por exemplo, posso dizer
int v[n];
se o valor de n só se torna conhecido durante a execução do
programa?
8-É verdade que devemos atribiuir NULL a cada ponteiro que
se tornou inútil ou desnecessário?
9-Deveríamos usar a função calloc ao invés de malloc?
Alocação dinâmica de memória

Entregar exercícios até dia 01/04/2019

Você também pode gostar