Apresentação na matéria de linguagem de programação, em 2010, no curso de Análise e Desenvolvimento de Sistemas da Unicamp
Size: 377.64 KB
Language: pt
Added: Oct 07, 2017
Slides: 22 pages
Slide Content
Bruno Luis Silveira Andretta
Bruno Silva de Oliveira
Fábio Junco Amaral
Hector Ferreira da Silva
Alocação de Memória
Alocação Estática x Dinâmica
• A linguagem de programação C/C++ permite dois tipos de
alocação de memória: Estática e Dinâmica
- Na alocação estática, o espaço de memória para as variáveis é
reservado ainda na compilação, não podendo ser alterado
depois:
int a;
int b[20];
- Na alocação dinâmica, o espaço de memória para as variáveis
pode ser alocado dinamicamente durante a execução do programa.
Uso da Memória
•Uso de variáveis globais (e estáticas):
–espaço reservado para uma variável global existe enquanto o
programa estiver sendo executado
•Uso de variáveis locais:
–espaço existe apenas enquanto a função que declarou a
variável está sendo executada, liberado para outros usos
quando a execução da função termina
•Variáveis globais ou locais podem ser simples ou vetores:
–para vetor, é necessário informar o número máximo de
elementos pois o compilador precisa calcular o espaço a
ser reservado
Alocação Dinâmica
Alocação Dinâmica
•Espaço de memória é requisitado em tempo de execução
•Espaço permanece reservado até que seja explicitamente
liberado
–depois de liberado, espaço estará disponibilizado para outros
usos e não pode mais ser acessado
–espaço alocado e não liberado explicitamente, será
automaticamente liberado quando ao final da execução
Alocação Dinâmica
Usamos alocação dinâmica quando não sabemos, no momento da
programação, a quantidade de dados que deverão ser inseridos.
É tentar responder a perguntas: quantas pessoas existem em sua turma?
Quantas letras vamos escrever, etc. Em vez de estarmos a prever um limite
superior para abarcar todas as situações, temos esta possibilidade do
dinâmico.
Além de que colocar no momento da programação cria reserva de memória por
isso, estaríamos a reservar memória para um limite que possivelmente não
iríamos ter necessidade. O exemplo típico disto é os processadores de texto.
em que não sabemos a quantidade de letras que o utilizador vai escrever.
Alocação Dinâmica
Alocação Dinâmica em C
•Funções principais (definidas na biblioteca “stdlib.h”)
–Função sizeof(...):
•retorna o número de bytes ocupado por um tipo
–Função malloc(...):
•recebe como parâmetro o número de bytes que se
deseja alocar
•retorna um ponteiro genérico para o endereço inicial
da área de memória alocada, se houver espaço livre.
Alocação Dinâmica em C
• Por exemplo:
–Alocação dinâmica de um vetor de inteiros com 10 elementos
–malloc retorna o endereço da área alocada para armazenar
valores inteiros
–ponteiro de inteiro recebe endereço inicial do espaço alocado
int *v;
v = (int *) malloc(10*sizeof(int));
Alocação Dinâmica em C
–v armazena endereço inicial de uma área contínua de
memória suficiente para armazenar 10 valores inteiros
–v pode ser tratado como um vetor declarado
estaticamente
• v aponta para o inicio da área alocada
• v[0] acessa o espaço para o primeiro elemento
• v[1] acessa o segundo
• .... até v[9]
Alocação Dinâmica em C
–tratamento de erro após chamada a malloc
• imprime mensagem de erro
• aborta o programa (com a função exit)
…
v = (int*) malloc(10*sizeof(int));
if (v==NULL)
{
printf("Memoria insuficiente.\n");
exit(1); /* aborta o programa e retorna 1 para o
sist. operacional */
}
…
Alocação Dinâmica em C
•Função free (...):
–recebe como parâmetro o ponteiro da memória a ser liberada
•a função free deve receber um endereço de memória que
tenha sido alocado dinamicamente
free (v);
Alocação Dinâmica em C
Alocação Dinâmica em C++
Alocação Dinâmica em C++
//Alocação Estática
#include <iostream>
int main ()
{
int numTests;
cout << "Entre com o número de teste:";
cin >> numTests;
int testScore[numTests];
system ("pause");
return 0;
}
//Alocação Dinâmica
#include <iostream>
int main ()
{
int numTests;
cout << "Entre com o número de teste:";
cin >> numTests;
int *testScore = new int [numTests];
system ("pause");
delete testScores;
return 0;
}
Operador New
O operador new retorna o endereço onde começa o bloco de memória, e como
retorna um endereço vamos colocá-lo num ponteiro.
É um operador cuja função é alocar memória dinamicamente.
Podemos inicializar de duas maneiras:
int *valor = new int; ou int *valor = new int(5);
*valor = 5; char *letra = new char('J');
Podemos criar vetores da seguinte maneira:
int *vetor = new int[10];
char *palavra = new char[40];
Operador Delete / Memory Leak
O tempo de vida de uma variável criada dinamicamente é o tempo de execução
do programa.
Se um ponteiro aponta para uma variável dinâmica e fica fora do escopo, já não
conseguiremos ter acesso a essa memória criada dinamicamente.
A isso chama-se Memory Leak.
Explicando:
Se alocamos memória dinamicamente dentro de uma função usando um
ponteiro local, quando a função termina, o ponteiro será destruído, mas a
memória mantém-se.
Assim já não teríamos formas de chamar essa memória porque ela não
tem nome. Apenas tínhamos o endereço que estava no ponteiro.
Portanto, se realmente não necessitamos mais dos dados que estão
nessa memória dinâmica, em vez de eles estarem a ocupar espaço vamos
apagá-los.
Necessitamos de libertar essa memória através do operador delete – este
operador entrega ao sistema operativo a memoria reservada dinamicamente.
A sintaxe é :
delete ponteiro;
delete [] vetor;
Este delete não apaga o pointer mas sim a memória onde o ponteiro aponta
Operador Delete
A alocação dinâmica funciona porque a memória não é reservada no momento
da compilação, mas antes na execução.
Em vez de ser no STACK (compilação) a memória é reservada no HEAP
(execução).
O heap é uma parte da memória que é usada como memória temporária.
Heap
void myfunction()
{
int *pt = new int(1024);
int local;
....
//Sem delete
}
int main()
{
while (condição)
{
myfunction();
}
return 1;
}
Heap
Quando a função “myfunction” é chamada a variável “local” é
criada no stack e quando a função acaba a variável é retirada
do stack.
O mesmo acontece com o ponteiro “pt”, ele é uma variável
local, ou seja, quando a função acaba, o ponteiro também
termina e é retirado do stack.
Porém a memória alocada dinamicamente ainda existe. E
agora não conseguimos apagar essa memória porque ela não
tem nome e a única maneira que tínhamos para saber onde ela
estava era através do ponteiro que terminou.
Então a medida que o programa continua a operar, mais e mais
memória será perdida do heap (memória livre).
Se o programa continuar o tempo suficiente, deixaremos de ter
memória disponível e o programa deixará de operar.
Na alocação dinâmica temos de nos certificar de que a alocação no heap foi
feita com sucesso e podemos ver isso de duas maneiras:
Uma é as excepções (este é o método default)
int *bobby = new int [5];
//se falhar, é tratado como “bad_alloc” exception
nothrow, aqui no caso de não se conseguir a memória retorna um ponteiro
nulo, e o programa continua.
int *bobby = new (nothrow) int [5];
//se falhar, o ponteiro recebe NULL
Verificar a existência de memória
Schildt, H. C++ Programming Cookbook.
http://www.dainf.ct.utfpr.edu.br/~karla/
Referências