Ponteiro em C: Alocação Dinâmica de Memória

funções X macros compilação condicional Diagnóstico

Recentemente o Felipe Neves apresentou neste artigo um sistema para gerenciamento de memória chamado TLSF. Além disso, destacou que esse tópico é bem discutido por quem desenvolve sistemas embarcados, apresentando opiniões bem divergentes. No entanto, independente do sistema de alocação dinâmica de memória, será sempre necessário operar com endereços de memória! Assim sendo, neste artigo, será destacada a função do ponteiro.

Alocação Dinâmica de Memória

A alocação dinâmica de memória é um mecanismo utilizado para possibilitar que uma quantidade de memória seja reservada durante o tempo de execução de uma aplicação. A região de memória utilizada para alocação dinâmica é conhecida como heap. Para saber mais sobre como um programa é organizado em memória consulte o primeiro artigo sobre ponteiros ou artigo sobre TLSF do Felipe Neves.

A biblioteca C padrão define 4 funções para alocação dinâmica de memória. Essas quatro funções são definidas na biblioteca STDLIB.H:

  • malloc;
  • calloc;
  • realloc;
  • free.

 

Veremos que em todas essas funções os ponteiros são utilizados! Mas antes será necessário apresentar um tipo de ponteiro que ainda não foi discutido nos artigos anteriores.

O Ponteiro void

Um ponteiro declarado como void é um ponteiro sem tipo! A função de um ponteiro void é simplesmente armazenar um endereço, pois nenhuma operação aritmética ou manipulação do conteúdo pode ser realizada. Um ponteiro do tipo void tem a seguinte forma:

Então, se em determinado momento é necessário apenas manter um endereço, um ponteiro void pode ser utilizado. Nas funções de alocação dinâmica essa característica pode ser observada uma vez que a função é genérica para qualquer tipo de dados.

Funções de Alocação Dinâmica de Memória

Começando pelas duas principais funções, malloc e free, temos as seguintes assinaturas:

O parâmetro size_t é utilizado para definir o tamanho de um bloco de dados que será alocado. Cabe ressaltar que o tamanho do bloco deve ser definido em bytes, sendo o operador sizeof, discutido no segundo artigo, essencial para garantir a portabilidade. Note que o retorno da função malloc é um ponteiro do tipo void. Esse ponteiro representa o endereço do bloco de dados alocado.

A função free, ao contrário da função malloc, deve ser utilizada para liberar um bloco alocado. É importante ressaltar que o endereço passado para função free deve ser um endereço obtido por uma das funções de alocação. Qualquer valor informado que não corresponda ao endereço inicial de um bloco alocado pode destruir o sistema de alocação.

As outras duas funções de alocação são mostradas abaixo:

A função calloc tem a mesma operação malloc, isto é, reserva um bloco de memória com base na quantidade de bytes informada. A diferença está nos parâmetros recebidos. Essa função recebe no primeiro parâmetro a quantidade de elementos que serão alocados, já no segundo parâmetro é informado o tamanho do tipo de dado.

A função realloc pode ser utilizada para redimensionar um bloco. Deste modo, um bloco pode aumentar ou diminuir o seu tamanho em tempo de execução. Para esse tipo de operação a função realloc deve receber o endereço do bloco alocado e o tamanho em bytes que será definido na operação. O retorno da função é o endereço do novo bloco alocado.

Dever do programador

Cabe ressaltar que em todas as funções de alocação dinâmica é necessário validar o endereço retornado, pois essas funções retornam NULL se a quantidade informada não pode ser alocada. Lembre-se, do primeiro artigo, que o valor NULL não impede erros de execução, porém fornece uma alternativa para testar se o ponteiro armazena um endereço válido. Em alguns compiladores é necessário realizar o cast do endereço retornado. No padrão ANSI não é necessário, ficando a critério do programador realizar o cast de forma explícita.

Outro ponto muito importante é que a linguagem C não possui um gerenciamento automático do heap. Diante disso, é dever do programador liberar toda memória alocada na aplicação, evitando o que é chamado memory leak. O Sergio Prado já discutiu esse assunto e apresentou algumas ferramentas de teste. Vale a pena conferir!

Conclusão

Independente do mecanismo utilizado num sistema de alocação dinâmica os ponteiros têm uma função especial. Por tratar-se de um mecanismo dinâmico, isto é, que varia conforme a execução do programa, os ponteiros oferecem os recursos necessários para manipular endereços de blocos de memória. Esse assunto torna-se importante para discutir um tópico conhecido como tipo de dados abstrato.

Referências

[1] – Livro: C, completo e total – 3ª edição revista e atualizada. Herbert Schildt.

Fonte da imagem destacada: http://listamaze.com/top-10-programming-languages-for-job-security/

Outros artigos da série

<< Ponteiro em C: EstruturasPonteiro em C: Tipo de Dado Abstrato >>
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Software » Ponteiro em C: Alocação Dinâmica de Memória
Comentários:
Notificações
Notificar
guest
6 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Rafael Gebert
Rafael Gebert
11/01/2016 09:49

Ótimo artigo Fernando! Eu utilizo o malloc, realloc e free para alocação de objetos e recusos gráficos (gfx proprietária) em microcontroladores.
Você conhece alguma lib de código fonte aberto para alocação dinâmica em memória externa? Antes que você responda que posso apontar o Heap para região externa eu preciso fazer alocação dinâmica na memória interna e na memória externa do microcontrolador. Encontrei dois mas achei muito intricado o código. Obrigado!

Fernando Deluno Garcia
Fernando Deluno Garcia
Reply to  Rafael Gebert
12/01/2016 09:42

Olá, Rafael.

Não conheço outra lib. Neste link tem algumas configurações que podem ser realizadas com memória interna x memória externa.

http://www.nongnu.org/avr-libc/user-manual/malloc.html

Quando precisei trabalhar com recursos gráficos montei um pequeno gerenciador de memória, mas não precisava alocar espaço para muitos objetos. Pois, o principal objetivo era poder criar o objeto em tempo de execução….

Obrigado pelo retorno!

Rafael Gebert
Rafael Gebert
Reply to  Fernando Deluno Garcia
12/01/2016 11:28

Obrigado pelo retorno Fernando! Eu também fiz um mini gerenciador de recursos para a memória externa… basicamente eu dividi uma região da memória externa em blocos de mesmo tamanho (como se fosse clusters de uma FAT) e quando vou carregar um recurso (seja uma imagem ou uma fonte e etc) eu varro a memória buscando por blocos vazios e retorno o ponteiro do endereço (como uma xmalloc). Mas não estou gerenciando um xfree e nem um xrealloc.
Obrigado!

Eder Andrade
Eder
08/01/2016 11:50

Mandou bem Fernando!

Fernando Deluno Garcia
Fernando Deluno Garcia
Reply to  Eder
11/01/2016 08:57

Obrigado, Eder.

Eder Andrade
Eder
Reply to  Fernando Deluno Garcia
15/01/2016 13:20

Fernando, dá até para você expandir o assunto, ou seja, ponteiro para ponteiro, alocação contínua ou não contínua de vetor e matriz. Isto aqui é show de bola 🙂

Talvez você goste:

Séries



Outros da Série

Menu

WEBINAR
 
BlueNRG-LP – Bluetooth 5.2 de longo alcance para aplicações industriais

Data: 05/11 às 15:00h - Apoio: STMicroelectronics
 
INSCREVA-SE AGORA »



 
close-link