Skip to content

10 - Alocação Dinâmica de Memória

Exercícios básicos

Hora de compilar!

Abra o arquivo ex1.c em um editor e compile-o usando as flags da disciplina.

$ gcc -Og -Wall -std=c99 ex1.c -o ex1

Sem rodar o programa, responda as questões abaixo.

Exercise

Analisando seu código-fonte, o que este programa faz?

Answer

Aloca um vetor, preenche com 0,1,...,n e imprime!

Exercise

Na execução deste programa, o que acontece se malloc falhar?

Answer

A função de alocação irá retornar NULL, mas nenhuma verificação está sendo feita.

Exercise

O seu programa libera toda memória que aloca? Se não, aponte onde ele deveria fazer isto.

Answer

Cada valor retornado por malloc deve ser liberado usando a função free. No caso, vemos que vetor não foi liberado após seu uso. Isto deveria ser feito na linha 26.


Agora execute o programa acima e responda as questões abaixo.

Exercise

Ocorreu algum problema durante a execução?

Answer

A resposta aqui é provavelmente não. Porém, isso não significa que o programa está correto, apenas que se ocorreu um erro ele não foi suficientemente grave para finalizar o programa.

Exercise

O comportamento de seu programa muda conforme N muda? Começe com N=10 e vá incrementando de um em um. Você consegue explicar por que? Discuta com seu grupo e valide sua resposta com o professor.

Answer

Ao chegar em N=14 seu programa deverá magicamente dar problemas e deve voltar a funcionar com N=15. Este é um dos grandes problemas de programas com erro de memória: seu comportamento é imprevisível.

Exercise

Existem três problemas no código. O primeiro (vetor não é desalocado) já identificamos no exercíco anterior. Você consegue identificar os outros dois?

Answer

O loop de exibição imprime até a posição N, porém as N posições do array são 0,1,\dots,N-1. O mesmo erro é realizado na função atribui, que faz um acesso indevido vetor[N].

Vamos corrigir!

Corrija os erros apontados na questão anterior e salve o programa em um arquivo ex1-certo.c.

Ferramentas de verificação de memória

Para poder identificar mais facilmente problemas relativos a memória, iremos utilizar uma ferramenta chamada Valgrind.

O Valgrind é um detector de má gestão de memória. Ele roda seu programa em cima de um ambiente modificado e aponta os seguintes erros:

  1. memória alocada e não liberada
  2. acessos (leituras e escritas) a posições de memória não alocada ou inválidas

O valgrind está disponível na maioria das distribuições Linux modernas. Instale com:

$ sudo apt update
$ sudo apt install valgrind

Dica

É recomendável manter o hábito de atualizar o Linux de tempos em tempos. Faça com:

$ sudo apt update
$ sudo apt upgrade

Para que os problemas encontrados pelo Valgrind sejam mais facilmente identificados, iremos passar a compilar utilizando a flag -g.

Example

Compile os programas ex1 e ex1-certo criados na parte anterior incluindo também a flag -g.

$ gcc -Og -g -Wall -std=c99 ex1.c -o ex1
$ gcc -Og -g -Wall -std=c99 ex1-certo.c -o ex1-certo

Exercise

Rode o Valgrind com valgrind --leak-check=yes ./ex1. Quantos erros foram encontrados? Quais são seus tipos (escrita ou leitura de dados)? O que eles significam?

Answer

Iremos discutir cada um dos erros!


O primeiro erro encontrado é

==1899== Invalid write of size 4
==1899==    at 0x1086C7: main (ex1.c:11)
==1899==  Address 0x522f078 is 0 bytes after a block of size 56 alloc'd
==1899==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1899==    by 0x1086B9: main (ex1.c:7)

Exercise

Em qual linha o erro ocorre? O que a mensagem acima significa?

Answer

O erro ocorre na linha 11, ao escrever em vetor[i] quando i == N


O segundo erro é

==1899== Invalid read of size 4
==1899==    at 0x1086DD: main (ex1.c:15)
==1899==  Address 0x522f078 is 0 bytes after a block of size 56 alloc'd
==1899==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1899==    by 0x1086B9: main (ex1.c:7)

Exercise

Em qual linha o erro ocorre? O que a mensagem acima significa?

Answer

O erro ocorre na linha 15, ao ler vetor[i] quando i == N.


A seção HEAP SUMMARY faz um resumo dos dados alocados/desalocados no seu programa. A saída abaixo foi obtida ao rodar o valgrind para o exercício 1 original:

==2179== HEAP SUMMARY:
==2179==     in use at exit: 56 bytes in 1 blocks
==2179==   total heap usage: 2 allocs, 1 frees, 1,080 bytes allocated
==2179==
==2179== 56 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2179==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2179==    by 0x1086B9: main (ex1.c:7)

Exercise

Ela mostra algum problema? Se sim, qual linha de código é apontada? Qual é o problema diagnosticado por este aviso?

Answer

Ela indica que houveram 2 mallocs' e somente 1free. Ou seja, alguma alocação de memória deixou de liberar dados. Abaixo, são indicadas em quais linhas osmallocsemfreeocorreram (linha 7 na funçãomain`)

Example

Verifique que seu programa corrigido ex1-certo.c roda sem erros no valgrind. Se não, corrija os problema e rode novamente até que rode sem erros.

Implementações de funções (Entrega)

Os exercícios abaixo estão disponíveis no repositório de entregas (pasta atv/08-malloc).

Dica!

Leia o README.md na pasta da atividade!

To Do

Abra o arquivo copia_string.c e implemente a função mystrcpy. Esta função recebe uma string, e devolve uma cópia da string original, alocando apenas o espaço realmente necessário.

To Do

Abra o arquivo concatena_string.c e implemente a função mystrcat. Esta função recebe duas string, e devolve uma terceira que é a concatenação das duas primeiras, alocando apenas o espaço realmente necessário.

Atenção!

Não se esqueça de checar se sua implementação tem erros usando o valgrind.