Já vimos como os alocadores funcionam. Mas,o que acontece com o free, o desalocador de memória? Ele realmente devolve a memória que eu utilizei para o sistema operacional? A resposta é um vigoroso, estrondoso e surpreendente não. Para um bom entendimento, aqui está o protótipo da função free:
void free(void *ptr);
Como a biblioteca Standard C foi projetada para administrar uma lista de blocos livres o que a função free faz é localizar a entrada na lista de memória do endereço que lhe foi passado como parâmetro. Uma vez localizado, free marca o bloco como disponível e isso é tudo. A função free não faz nenhuma chamada de sistema.
Este funcionamento é muito interessante pois o Standard C preocupou-se com 2 fatores: performance e portabilidade. A alocação de memória, quando ocorre uma chamada de sistema (system call para os mais puritanos), é na verdade o redimensionamento do espaço de endereçamento do seu processo. Esta memória extra, chamada de heap, é, na verdade, o espaço extra que aparece no seu processo após o seu redimensionamento. O fato é que para devolver efetivamente memória ao sistema operacional, seria necessário redimensionar o espaço de endereçamento do seu processo para menos. No entanto, não são todos os sistemas operacionais que permitem tal operação.
Para que fosse totalmente portável, o Standard C utilizou a forma como os alocadores de memória trabalham no Unix, pois na época em que o padrão estava sendo escrito o Unix não permitia o redimensionamento de um processo para "menos".
[1] Comentário enviado por espinafre em 29/06/2004 - 11:28h
Bastante interessante... Eu havia notado um comportamento estranho no Apache: eu tinha um script PHP que necessitava de uma enormidade de memória (coisa de 200MB). Usando o gnome-system-monitor, vi o uso de memória do sistema crescer para mais de 400MB enquanto o programa executava (só o Apache, e portanto meu programa PHP, usava em torno de 300MB). Depois que o programa terminou, esses 300MB não foram liberados pelo sistema. Trem doido, sô!
[4] Comentário enviado por nick_skyp em 16/01/2005 - 04:47h
realmente mto interessante!!
parabeins.. ms pintou uma duvida aki...
a STD C é implementada em C, certo?
ela usa "lista circular" para guardar areas de memoria(livres ou naum), ateh aeh blza... ms jah qdo se fala em lista, eu soh consigo pensar em alocação dinâmica... :-) naum sei se eh assim q funciona na STD C, ms essa lista na verdade tem tamanho limitado? (estatica)...
se naum, como eh que funciona o processo de "criação dos nós dessa 'lista livre' ?? (dinamica), senão atraves do sistema operacional ou pelo uso de seus proprios nós?? "
humm.. fikou confuso agora :S...
[5] Comentário enviado por ron_lima em 16/01/2005 - 08:50h
A lista livre nada mais é que uma lista encadeada. Sempre que as funções calloc, malloc ou realloc solicitam mais memória do sistema operacional, esta nova arena de memória é ligada à esta lista. Esta lista não tem limite e a quantidade de memória a ser alocada é limitada pelo sistema operacional.
Quando seu programa chama a função "free", na verdade a arena de memória passada como parâmetro volta à lista encadeada, onde é marcada como "disponível para realocação". Este comportamento tem uma vantagem em termos de performance, pois qualquer realocação de memória subseqüente não será realizada através de chamadas de sistema.
No caso do que o espinafre disse, o efeito é este mesmo: seu programa jamais vai liberar memória de volta para o sistema operacional. Por exemplo, se o seu programa tem um core de tamanho 10k e aloca mais 10k, ele ficará, durante toda sua execução, ocupando 20k de memória, mesmo que você chame a função free exaustivamente. Como dito no artigo, a função free não libera memória para o sistema operacional, mas a disponibiliza em uma lista encadeada interna à biblioteca STDC para realocação futura.
Como boa literatura sobre o assunto, um excelente livro é o do Kernighan e Ritchie - Linguagem C, onde apresentam um alocador de memória simples. Outro excelente livro é A Biblioteca Standard C, de P.J. Plauger que participou do X3J11.
[6] Comentário enviado por ron_lima em 16/01/2005 - 08:52h
Detalhando um pouco mais a lista... Quando a memória é solicitada ao sistema operacional, a biblioteca STDC aloca, na verdade, um pouquinho mais. Este "pouquinho" é para conter os pointers que serão usados para a ligação na lista livre.
[7] Comentário enviado por ron_lima em 16/01/2005 - 08:55h
Hilmilho, no caso do programa em PHP, realmente a memória não será liberada. O que ocorre é que o apache trabalha carregando módulos em seu espaço de endereçamento. Assim, o engine PHP será carregado dentro do espaço de endereçamento do apache. O que quer que o PHP aloque de memória ficará preso dentro do apache.
Existe uma forma de configurar isso, acredito eu, que é tornar o apache um servidor multi-processo. Assim, todas as solicitações que chegarem serão processadas por um processo filho que liberará tudo o que for alocado quando terminar.
Esta configuração torna o apache muito pesado pois é mais suave para o SO criar uma thread do que um processo inteiro. Sem falar que a criação de um processo inteiro provoca a duplicação de todo o address space do processo pai, o que é um senhor overhead.
[8] Comentário enviado por nick_skyp em 16/01/2005 - 17:14h
humm.. valeu explicou melhor.. qestao da lista agora...
na verdade em um caso bem particular.. esse "poukinho alocado a mais pelo STD C" pode resultar por exemplo em um MALLOC retornando NULL... certo!?? ^^
[9] Comentário enviado por ron_lima em 16/01/2005 - 22:00h
Não. Este pouquinho a mais usualmente não ultrapassa mais que 4 bytes, dependendo da plataforma (em plataformas de 64 bits, este valor chega a 8 bytes). Se bem que isso depende, muito, da implementação da libC que você esteja usando. Esta é uma estimativa. A implementação do lib STDC é extremamente dependente do sistema operacional. As interfaces são sempre as mesmas, mas a implementação difere consideravelmente .Por exemplo, chamadas de sistema em uma máquina linux são completamente diferentes das chamadas de sistema em uma máquina Solaris.
A família de alocação de memória do STDC (malloc, calloc e realloc) podem retornar um ponteiro nulo apenas quando não há mais como obter memória para retornar ao programa. Isso acontece da seguinte maneira: Seu programa requisita memória à biblioteca STDC, seja chamando malloc, calloc ou realloc. Estas funções, em um primeiro momento, irão tentar localizar uma arena de memória com o tamanho solicitado na lista livre. Caso não exista, estas funções vão solicitar memória ao sistema operacional. Porém, se o processo chegou a um determinado limite, seja por imposição do administrador do sistema em alguns sistemas, seja por que realmente não existe mais memória disponível para alocação, a chamada de sistema irá falhar. Esta falha é traduzida pelas funções como um ponteiro inválido, cujo valor é zero (a macro NULL expande para a constante 0, que pode ser long dependendo do sistema).
O que se precisa ter em mente é que a idéia dos alocadores de memória do STDC é isolar seu programa da interface do sistema operacional, tornando, assim, seu programa independente de plataforma. Se você programar para unix usando o STDC, é garantido que seu programa funciona em Windows, Windows CE, Palm OS, BeOS e por aí vai.
[10] Comentário enviado por nick_skyp em 17/01/2005 - 04:48h
certo... valeu pelos esclarecimentos... ms qeria q c respondesse(se puder)... a pergunta q fiz no artigo de "introdução as bibliotecas em C"..
ateh logo e parabeins pelos artigos!
[14] Comentário enviado por ron_lima em 10/11/2008 - 18:44h
Os alocadores de memória do C++ funcionam exatamente da mesma maneira, ou seja, solicitam ao sistema operacional mais memória (caso do new) e devolvem a um pool interno no caso da desalocação (caso do delete). Da mesma maneira, o delete não devolve ao sistema operacional a memória alocada. A diferença básica é que estes operadores do C++ fazem um pouco mais do que apenas alocarem memória. No caso do new, ele também chama o construtor da sua classe e no caso do delete, o destrutor.
[15] Comentário enviado por ryonagana em 15/12/2008 - 18:21h
sim claro, é que eu confesso que nao sei usar malloc, calloc essas coisas
apesar de ser muito util, mas acho que esses comandos de C sao muito abaixo do nivel do c++
MAS se caso a pessoa quiser dar uma compatibilidade a mais, aconselho a usar esse modo
ou se a pessoa estiver programando um framework ,ou um sistema operacional e quiser fazer uma abstração de codigo