Muita gente que programa não sabe como realmente a memoria é administrada e isso graças as camadas de abstrações criadas pelo sistema operacional, que tentam facilitar a vida não importando se é um programador ou um usuário final.
Muita gente que programa não sabe como realmente o sistema
operacional faz para administrar sua memória. Isso graças as
camadas de abstrações criadas pelo S.O. que tentam facilitar
a vida não importando se é um programador ou um usuário final.
Afim de facilitar o aprendizado do funcionamento da memória,
vamos imaginar a memória como sendo um grande vetor para se
guardar dados, mas quero destacar que esse tipo de pensamento
é uma forma muito "grosseira", pois leva a pensar que os dados
vão ser alocados de uma maneira linear e/ou seqüencial.
A memória é dividida em 2 tipos: Stack e Heap, mas
alguns livros dizem que existem 3 tipos: automática,
estática e dinâmica. A diferença básica entre esses
tipos é nada mais que a forma como ele é tratado.
A Stack (ou Automática/Pilha) é onde guardamos as
variáveis locais nos programas. Já a Heap (ou estática) é
assim chamada porque seus valores permanecem até o fim do programa.
Na memória Heap, por exemplo, guardamos variáveis globais,
constantes e variáveis definidas "static" no C.
Por fim, toda a memória que não é estática nem automática é
dinâmica. A memória dita dinâmica viria após a Heap.
Vejamos uma figura de como ficaria essa divisão da memória:
Assim podemos notar claramente que conforme for sendo solicitado
mais memória. O S.O. vai reservando memória conforme a definição
já dada. O jeito mais comum de se imaginar a memória é ela por
vetor de linhas (de pé?) e não por colunas (deitado?). Assim, a
alocação da memória é sempre de cima pra baixo, dependendo da área
que se vai utilizar.
Você deve estar se perguntando: "Como isso pode ser útil pra
minha vida?". Eu respondo, é "Cultura". :D
Falando sério, isso ajuda a deixar mais claros alguns erros muito
comuns. Primeiro, imaginar a memória como nós fizemos. Eu li em
algum lugar que "quanto mais fácil de se visualizar a memória,
mais longe da realidade ela está", mas que facilita, facilita.
O segundo lugar que podemos usar isso é pra compreender erros
comuns como "Stack Overflow", que nada mais é a "pilha
sobrecarregada", ou seja, ela cresceu tanto que está invadindo uma
área que originalmente não é dela.
Terceiro, "Cultura é essencial" hehehehe.
[]'s
NOTA: Já ia esquecendo, as figuras originais foram pegas do site
www.olinux.com.br, no curso
de C deles. As adaptei pra usar aqui. Espero que tenham gostado.
NOTA2: Tentei ser o mais generico possivel.
[4] Comentário enviado por peace em 23/02/2004 - 09:59h
Muito bom o artigo. Nos dá uma boa idéia do "porque" de alguns problemas que as vezes não entendemos. E no meu caso, programador iniciante, também é uma ótima ajuda!
[7] Comentário enviado por cardosoalcir em 09/10/2004 - 13:35h
Kra otimo assunto para um artigo, eu que sou programador iniciante ja havia me deparado com ários problemas sem nem imaginar que poderia ser memoria, muito obrigado e parabens :D
[9] Comentário enviado por ron_lima em 14/06/2007 - 13:25h
O stack overflow normalmente ocorre por que uma função recursiva mal implementada se aprofundou demais nas suas chamadas na fase ativa. O tamanho da pilha (stack) pode ser alterado através de parâmetros passados ao compilador. Em ambientes Windows, a pilha é definida como tendo 1M de tamanho, justamente para evitar recursão infinita.
Normalmente o ajuste do compilador é suficiente para o tamanho da pilha e não há a necessidade de alterar-se isso, a não ser que você trabalhe com sistemas onde o tamanho da pilha seja muito limitado.
Parabéns pelo artigo, jlluca. Ficou muito bom mesmo!
[11] Comentário enviado por OneSr em 28/05/2010 - 00:44h
É cara, eu estou estudando isso, realmente o estouro de pilha pode ser uma complicação gigantesca, ótimo artigo. Lógico que se formos estudar o alojamento de memória lógica em memória física a fundo é muito mais que isso, más é relativamente meio que inútil nos dias atuais com as tecnologias computacionais que estão a ser lançadas, isso é mais mesmo pra aplicações muito pesadas, e que alocam um processo muito grande na memória física...outra coisa que já está praticamente contornada com os alojamentos apenas de partes necessárias na memória física. É, isso é realmente para programadores que querem trabalhar bem próximos aos 0's e 1's hehehe, não é meu caso =p
[12] Comentário enviado por berr em 26/11/2011 - 01:04h
Olá, no seguinte parágrafo tem um equívoco de tradução, eu imagino.
A diferença básica entre esses tipos é nada mais que a forma como ele é tratado. A Stack (ou Automática/Pilha) é onde guardamos as variáveis locais nos programas. Já a Heap (ou estática) é assim chamada porque seus valores permanecem até o fim do programa. Na memória Heap, por exemplo, guardamos variáveis globais, constantes e variáveis definidas "static" no C.
Existem 3 tipos de variáveis: Estáticas, Automáticas e Dinâmicas.
Variáveis estáticas são as variáveis globais (que não são declaradas dentro de funções) ou com a keyword específica da linguagem.
Essas variáveis são alocadas em tempo de compilação, e ficam numa área do programa chamada de "área de dados estáticos".
Variáveis são automáticas são as variáveis declaradas dentro de uma função. A alocação dela é feita na Pilha (stack) automaticamente a cada entrada na função. Por isso, se você tiver muitas chamadas de função aninhadas pode ocorrer um stack overflow (é quando a stack
encosta na heap)
Variáveis dinâmicas são as variáveis alocadas pelo usuário. Em C são alocadas com malloc, em C++ com o new. Essas variáveis são alocadas pelo usuário e não são desalocadas (ao contrário de variáveis automáticas, que são desalocadas ao sair da função). O problema de usar variáveis dinâmicas é você alocar ela, não desalocar e perder a referência. Assim você terá "perdido" um pouco da memória do sistema (o nome disso é Memory Leak). Quando o programa termina, toda a sua memória alocada, inclusive a dinamicamente alocada, volta ao controle do sistema operacional