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:
- memória alocada e não liberada
- 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 1
free. Ou seja, alguma alocação de memória deixou de liberar dados. Abaixo, são indicadas em quais linhas os
mallocsem
freeocorreram (linha 7 na função
main`)
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.