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.
Sem rodar o programa, responda as questões abaixo.
Exercise 1
Answer
Aloca um vetor, preenche com $0,1,...,n$ e imprime!
Exercise 2
Answer
A função de alocação irá retornar NULL
, mas nenhuma verificação está sendo feita.
Exercise 3
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 4
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 5
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 6
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. Para saber mais sobre o valgrind acesse o link:
https://diveintosystems.org/book/C3-C_debug/valgrind.html
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:
Dica 1
É recomendável manter o hábito de atualizar o Linux de tempos em tempos. Faça com:
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
.
Exercise 7
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 8
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 9
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 10
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 malloc
sem free
ocorreram (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! 2
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.