DCC024 Linguagens de Programac¸ ˜ao
2020/1
Gerenciamento de mem ´ oria
Haniel Barbosa
Mem ´ oria
B
Quais componentes de um programa precisam ser armazenados?I o programa em si
Operac¸ ˜oes a serem executadas
I o estado do programa
Valores manipulados por essas operac¸ ˜oes
B
Amem ´oria ´e onde esses componentes s ˜ao armazenadosB
Veremos como gerenciar a mem ´oria para o estado de um programaGerenciamento de mem ´ oria no interpretador de micro-ML
B
O interpretador de express ˜oes mantinha o estado de vari ´aveis[(‘‘a”, 5), (‘‘f”, ‘‘x”, Prim2(‘‘+”, Var ‘‘x”, Var ‘‘a”), [(‘‘a”, 3)]), ...]
B
Oarmazenamentode valores se dava pela inserc¸ ˜ao na cabec¸a da lista I Definic¸ ˜ao de um novo escopoB
Aremoc¸ ˜aode valores se dava pela remoc¸ ˜ao da cabec¸a da lista I Sa´ıda de um escopoB
Oacessoa valores durante a interpretac¸ ˜ao da express ˜ao se dava por uma busca na listaPossibilitar, de forma eficiente e segura, oacesso,armazenamentoeremoc¸ ˜ao de dados ´e o problema central de gerenciamento de mem ´oria.
Gerenciamento de mem ´ oria no interpretador de micro-ML
B
O interpretador de express ˜oes mantinha o estado de vari ´aveis[(‘‘a”, 5), (‘‘f”, ‘‘x”, Prim2(‘‘+”, Var ‘‘x”, Var ‘‘a”), [(‘‘a”, 3)]), ...]
B
Oarmazenamentode valores se dava pela inserc¸ ˜ao na cabec¸a da lista I Definic¸ ˜ao de um novo escopoB
Aremoc¸ ˜aode valores se dava pela remoc¸ ˜ao da cabec¸a da lista I Sa´ıda de um escopoB
Oacessoa valores durante a interpretac¸ ˜ao da express ˜ao se dava por uma busca na listaPossibilitar, de forma eficiente e segura, oacesso,armazenamentoeremoc¸ ˜ao de dados ´e o problema central de gerenciamento de mem ´oria.
Gerenciamento de mem ´ oria em C
i n t g l o b a l v a r = 7 ;
void f o o (i n t* p t r )
{
i n t a u t o v a r = 9 ; p t r [ 0 ] = g l o b a l v a r ; p t r [ 1 ] = a u t o v a r ;
}
i n t main ( )
{
i n t* p t r = (i n t* ) m a l l o c ( 5 * s i z e o f(i n t) ) ; f o o ( p t r ) ;
p t r [ 2 ] = p t r [ 1 ] + g l o b a l v a r ;
}
Tipos de mem ´ oria
B
Est ´atica I Permanente I Vari ´aveis globaisB
Din ˆamica I StackArmazenamento feito quando um escopo ´e criado (push) Remoc¸ ˜ao quando o escopo ´e destru´ıdo (pop)
Gerenciamento autom ´atico
I Heap
Piscina de blocos de mem ´oria, virtualmente ilimitada Armazenamento/remoc¸ ˜ao feitos independente de escopos Gerenciamento manual
Est ´atica vs Din ˆamica
⊕
Mem ´oria est ´atica n ˜ao tem custo extra de gerenciamento durante execuc¸ ˜ao
Mem ´oria est ´atica n ˜ao ´e flex´ıvelI Se execuc¸ ˜ao precisar de menos mem ´oria, haver ´a desperd´ıcio I Se execuc¸ ˜ao precisar de mais mem ´oria, impossibilitar ´a a execuc¸ ˜ao
⊕
Mem ´oria din ˆamica ´e flex´ıvel:I pode-se usar apenas o estritamente necess ´ario para uma execuc¸ ˜ao I Limitada apenas pelo total de mem ´oria no dispositivo
Mem ´oria din ˆamica tem custo de gerenciamento durante a execuc¸ ˜aoStack vs Heap
⊕
Armazenamento, remoc¸ ˜ao e acesso na stack s ˜ao simples
Stack possui tamanho pr ´e-determinado, ent ˜ao pode ocorrerstack overflow I Vari ´aveis locais requerendo mais mem ´oria do que o limiteI Recurs ˜ao muito profunda levando a mais escopos do que o limite
⊕
Heap limitada apenas pela mem ´oria do dispositivo
Armazenamento, remoc¸ ˜ao e acesso s ˜ao custosos e/ou complexosGerenciamento de mem ´ oria na heap
B
Considere a heap como um conjunto deunidades de mem ´oriaindexado por inteiros (i.e., um vetor)B
Considere umalista de blocos livresdenotando partes desocupadas da heap I Cada elemento da lista cont ´em: a posic¸ ˜ao de in´ıcio do bloco livre, seu tamanho, euma refer ˆencia ao bloco livre seguinte
I Inicialmente a lista cont ´em um bloco livre englobando toda a mem ´oria
B
O armazenamento de dados na heap reserva blocos (segmentos cont´ıguos da mem ´oria) cuja primeira posic¸ ˜ao cont ´em o tamanho do blocoArmazenamento e remoc¸ ˜ao de dados da heap
Considere os seguintes m ´etodos:
B
allocate(n : Int
) :(a : Int)
I Acha o primeiro blocoao menosde tamanhon+1na lista de blocos livres I Cria um bloco de tamanhon+1comec¸ando na posic¸ ˜aoado bloco livre. O
tamanho do bloco ´e salvo na posic¸ ˜aoa
I O restante do bloco livre se torna um novo bloco livre e ´e adicionado `a lista
B
deallocate(a : Int
)I Remove o bloco na posic¸ ˜aoae o adiciona `a cabec¸a da lista de blocos livres
B
Exemplo: considere uma heap m de tamanho 10p1 = m.allocate(4);
p2 = m.allocate(2);
m.deallocate(p1);
p3 = m.allocate(1);
Armazenamento e remoc¸ ˜ao de dados da heap
Considere os seguintes m ´etodos:
B
allocate(n : Int
) :(a : Int)
I Acha o primeiro blocoao menosde tamanhon+1na lista de blocos livres I Cria um bloco de tamanhon+1comec¸ando na posic¸ ˜aoado bloco livre. O
tamanho do bloco ´e salvo na posic¸ ˜aoa
I O restante do bloco livre se torna um novo bloco livre e ´e adicionado `a lista
B
deallocate(a : Int
)I Remove o bloco na posic¸ ˜aoae o adiciona `a cabec¸a da lista de blocos livres
B
Exemplo: considere uma heap m de tamanho 10p1 = m.allocate(4);
p2 = m.allocate(2);
m.deallocate(p1);
p3 = m.allocate(1);
Exemplos de uso da heap
B
E se tiv ´essemos as seguintes operac¸ ˜oes?p1 = m.allocate(4);
p2 = m.allocate(4);
m.deallocate(p1);
m.deallocate(p2);
p3 = m.allocate(7);
B
Apesar de a mem ´oria, de tamanho 10, estar totalmente livre, est ´a dividida em dois blocos livres adjacentes de tamanho 5 cada.Exemplos de uso da heap
B
E se tiv ´essemos as seguintes operac¸ ˜oes?p1 = m.allocate(4);
p2 = m.allocate(4);
m.deallocate(p1);
m.deallocate(p2);
[fails] p3 = m.allocate(7);
B
Apesar de a mem ´oria, de tamanho 10, estar totalmente livre, est ´a dividida em dois blocos livres adjacentes de tamanho 5 cada.Combinac¸ ˜ao de blocos livres
B
Combinar blocos livres adjacentes permite o armazenamento no caso anteriorB
Manter a lista de blocos livres ordenada pela posic¸ ˜ao de in´ıcio dos blocos permite f ´acil combinac¸ ˜aoB
Basta um novo bloco ser adjacente ao seu antecessor ou sucessor na lista para uma combinac¸ ˜ao ser poss´ıvelFragmentac¸ ˜ao de mem ´ oria
B
A soluc¸ ˜ao anterior s ´o ´e suficiente para blocos adjacentesB
Exemplo:p1 = m.allocate(3);
p2 = m.allocate(2);
m.deallocate(p1);
p3 = m.allocate(2);
p4 = m.allocate(3);
B
Apesar de a mem ´oria possuir, em princ´ıpio, espac¸o o suficiente, ela est ´a fragmentadaFragmentac¸ ˜ao de mem ´ oria
B
A soluc¸ ˜ao anterior s ´o ´e suficiente para blocos adjacentesB
Exemplo:p1 = m.allocate(3);
p2 = m.allocate(2);
m.deallocate(p1);
p3 = m.allocate(2);
[fails] p4 = m.allocate(3);
B
Apesar de a mem ´oria possuir, em princ´ıpio, espac¸o o suficiente, ela est ´a fragmentadaOnde armazenar blocos?
B
Diferentes possibilidades com vantagens e desvantagens. Alguns exemplos:B
First fitI Armazenamento no bloco compat´ıvel com a menor posic¸ ˜ao na mem ´oria
⊕ Simples e eficiente
Pode separar blocos grandes mais facilmente
B
Best fitI Armazenamento no bloco compat´ıvel de menor tamanho
⊕ Maior sinergia entre bloco a ser armazenado e blocos dispon´ıveis
Pode levar a blocos muito pequenos mais facilmente
Implementac¸ ˜ao mais complexa da lista de blocos para acesso eficiente (e.g., ´arvores rubro-negras)
Evitando fragmentac¸ ˜ao de mem ´ oria no exemplo anterior
B
Com armazenamento porbest fito exemplo ´e bem-sucedido:B
Exemplo:p1 = m.allocate(3);
p2 = m.allocate(2);
m.deallocate(p1);
p3 = m.allocate(2);
[works!] p4 = m.allocate(3);
B
O bloco apontado por p3 n ˜ao mais ´e alocado no comec¸oB
Um bloco de tamanho 4 est ´a dispon´ıvel para o armazenamento apontado por p4.Tr ˆes principais aspectos do gerenciamento da heap
B
Placement: dentre v ´arios blocos livres, em qual realizar o armazenamento I First fit, best fit, ...B
Splitting: quando e como separar grandes blocos livres de mem ´oria I pode ser melhor n ˜ao gerar blocos livres de tamanhos “incomuns” durante oarmazenamento
B
Coalescing: quando e como recombinar blocos de mem ´oriaI em casos com frequente armazenamento de pequenos blocos pode ser melhor n ˜ao recombinar blocos adjacentes, ou faz ˆe-lo s ´o quando necess ´ario
Erros devido ao mau uso de mem ´ oria
B
O gerenciamento manual de mem ´oria pode levar a errosB
Um erro comum ´e n ˜ao remover blocos de mem ´oria armazenados I Vazamentos de mem ´oria (Memory leaks)I Pode levar a um consumo excessivo de mem ´oria
B
Um erro ainda mais perigoso ´e o de manter refer ˆencias a blocos de mem ´oria que foram removidosI Ponteiros cegos (Dangling pointers) I Pode levar a comportamentos inesperados
Exemplo de vazamento de mem ´ oria
void l e a k ( )
{
i n t* i = (i n t* ) m a l l o c (s i z e o f(i n t) ) ;
* i = 3 ;
p r i n t f ( ”%d
\
n ” , * i ) ;}
i n t main ( )
{
l e a k ( ) ;
}
Exemplo de ponteiro cego
void d a n g l i n g ( )
{
i n t* i = (i n t* ) m a l l o c (s i z e o f(i n t) ) ; i n t* j ;
* i = 3 ; f r e e ( i ) ;
j = (i n t* ) m a l l o c (s i z e o f(i n t ) ) ;
* j = 8 ;
p r i n t f ( ”%d
\
n ” , * i ) ;}
i n t main ( )
{
d a n g l i n g ( ) ;
}
Valgrind for fun and profit
B
Pode detectar vazamentos de mem ´oria$ valgrind ./11-mem-leak ...
==70445== LEAK SUMMARY:
==70445== definitely lost: 4 bytes in 1 blocks
==70445== indirectly lost: 0 bytes in 0 blocks
==70445== possibly lost: 0 bytes in 0 blocks
==70445== still reachable: 0 bytes in 0 blocks
==70445== suppressed: 0 bytes in 0 blocks
B
Pode detectar acessos inv ´alidos de mem ´oria$ valgrind ./11-mem-dangling ...
==71000== Invalid read of size 4
==71000== at 0x1091D5: dangling (in /home/hbarbosa/teaching/lp/codes/11-mem-dangling)
==71000== by 0x1091FE: main (in /home/hbarbosa/teaching/lp/codes/11-mem-dangling)
==71000== Address 0x4a5a040 is 0 bytes inside a block of size 4 free’d
==71000== at 0x483CA3F: free (in /usr/lib/x86˙64-linux-gnu/valgrind/vgpreload˙memcheck-amd64- linux.so)
==71000== by 0x1091B8: dangling (in /home/hbarbosa/teaching/lp/codes/11-mem-dangling)
==71000== by 0x1091FE: main (in /home/hbarbosa/teaching/lp/codes/11-mem-dangling)
==71000== Block was alloc’d at
==71000== at 0x483B7F3: malloc (in /usr/lib/x86˙64-linux-gnu/valgrind/vgpreload˙memcheck-amd64- linux.so)
==71000== by 0x10919E: dangling (in /home/hbarbosa/teaching/lp/codes/11-mem-dangling)
==71000== by 0x1091FE: main (in /home/hbarbosa/teaching/lp/codes/11-mem-dangling)
Coleta de lixo (Garbage collection)
B
Mau uso de mem ´oria pode ser evitado com abordagens autom ´aticas de remoc¸ ˜ao de blocos armazenados na heapB
Essas abordagens s ˜ao conhecidas como coleta de lixo I Remoc¸ ˜ao de blocos que n ˜ao s ˜ao mais utilizados (lixo)B
Geralmente requer determinar quais blocos da mem ´oria s ˜ao relevantes:I Dadas um conjunto inicial de interesse, adicionar todas as posic¸ ˜oes de mem ´oria alcanc¸ ´aveis a partir daquele conjunto e as adicionar ao conjunto
I Repetir at ´e um ponto fixo