Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois...

34
Alocação Dinâmica de Memória Bruno Hott Algoritmos e Estruturas de Dados I DECSI – UFOP

Transcript of Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois...

Page 1: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Alocação Dinâmica deMemória

Bruno HottAlgoritmos e Estruturas de Dados IDECSI – UFOP

Page 2: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 2

Alocação Estática x Dinâmica

● C: dois tipos de alocação de memória: Estática e Dinâmica

● Na alocação estática, o espaço para as variáveis é reservado no início da execução, não podendo ser alterado depois

int a;

int b[20];

● Na alocação dinâmica, o espaço para as variáveis pode ser alocado dinamicamente durante a execução do programa.

Page 3: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 3

Alocação Dinâmica

● As variáveis alocadas dinamicamente são chamadas de apontadores (pointers) pois na verdade elas armazenam o endereço de memória de uma variável

● A memória alocada dinamicamente faz parte de uma área de memória chamada heap (pilha)

– Basicamente, o programa aloca e desaloca porções de memória do heap durante a execução

Page 4: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 4

Esquema de Memória

Page 5: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 5

Acesso a partir de Apontadores

● Acessar o valor da variável: endereço de memória armazenado

● Acessar o conteúdo associado ao endereço de memória armazenado

● Liberação de Memória:

– A memória deve ser liberada após o término de seu uso

– A liberação deve ser feita por quem fez a alocação:● Estática: compilador● Dinâmica: programador

Page 6: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 6

Apontadores – Notação (c)

● Definição de p como um apontador para uma variável do tipo Tipo

Tipo *p;

● Alocação de memória para uma variável apontada por p

p = (Tipo*) malloc(sizeof(Tipo));

● Liberação de memória

free(p);

● Conteúdo da variável apontada por P

a = *p;

● Valor nulo para um apontador

p = NULL;

● Endereço de uma variável a

p = &a;

Page 7: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 7

Alocação Dinâmica

int *a, b;...b = 10;a = (int*) malloc( sizeof(int) );*a = 20;a = &b;

Page 8: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 8

Alocação Dinâmica

int *a, b;...b = 10;a = (int*) malloc( sizeof(int) );*a = 20;a = &b;

Page 9: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 9

Alocação Dinâmica

int *a, b;...b = 10;a = (int*) malloc( sizeof(int) );*a = 20;a = &b;

Page 10: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 10

Alocação Dinâmica

int *a, b;...b = 10;a = (int*) malloc( sizeof(int) );*a = 20;a = &b;

Page 11: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 11

Alocação Dinâmica

int *a, b;...b = 10;a = (int*) malloc( sizeof(int) );*a = 20;a = &b;

Page 12: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 12

Erros Comuns

● Esquecer de alocar memória e tentar acessar o conteúdo da variável

Page 13: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 13

Erros Comuns

● Esquecer de alocar memória e tentar acessar o conteúdo da variável

int *a, b;b = *a;

Page 14: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 14

Erros Comuns

● Esquecer de alocar memória e tentar acessar o conteúdo da variável

int *a, b;b = *a;

● Copiar o valor do apontador ao invés do valor da variável apontada

Page 15: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 15

Erros Comuns

● Esquecer de alocar memória e tentar acessar o conteúdo da variável

int *a, b;b = *a;

● Copiar o valor do apontador ao invés do valor da variável apontada

int *a, b;b = a;

Page 16: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 16

Erros Comuns

● Esquecer de alocar memória e tentar acessar o conteúdo da variável

int *a, b;b = *a;

● Copiar o valor do apontador ao invés do valor da variável apontada

int *a, b;b = a;

● Esquecer de desalocar memória

– Ela é desalocada ao fim do programa ou procedimento função onde a variável está declarada, mas pode ser um problema em loops

Page 17: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 17

Erros Comuns

● Esquecer de alocar memória e tentar acessar o conteúdo da variável

int *a, b;b = *a;

● Copiar o valor do apontador ao invés do valor da variável apontada

int *a, b;b = a;

● Esquecer de desalocar memória

– Ela é desalocada ao fim do programa ou procedimento função onde a variável está declarada, mas pode ser um problema em loops

● Tentar acessar o conteúdo da variável depois de desalocá-la

Page 18: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 18

Erros Comuns

● Esquecer de alocar memória e tentar acessar o conteúdo da variável

int *a, b;b = *a;

● Copiar o valor do apontador ao invés do valor da variável apontada

int *a, b;b = a;

● Esquecer de desalocar memória

– Ela é desalocada ao fim do programa ou procedimento função onde a variável está declarada, mas pode ser um problema em loops

● Tentar acessar o conteúdo da variável depois de desalocá-la

free(a);a = 10;

Page 19: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 19

Exercício:

double a;double *p;

a = 3.14;printf("%f\n", a);p = &a;*p = 2.718;printf("%f\n", a);a = 5.0;printf("%f\n", *p);

p = NULL;p = (double*) malloc( sizeof(double) );*p = 20.0;printf("%f\n", *p);printf("%f\n", a);

free(p);printf("%f\n", *p);

3.14

2.718

5.0

20.0

5.0

Erro!

Page 20: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 20

Pergunta que não quer calar...

● int *a não é a declaração de um vetor de int?

● Em C, todo apontador pode se comportar como vetor:

● Portanto pode-se fazer coisas como:int a[10], *b;b = a;b[5] = 100;printf(“%d\n”, a[5]);printf(“%d\n”, b[5]);

int a[10], *b;b = (int*) malloc(10*sizeof(int));b[5] = 100;printf(“%d\n”, a[5]);printf(“%d\n”, b[5]);

Page 21: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 21

Pergunta que não quer calar...

● int *a não é a declaração de um vetor de int?

● Em C, todo apontador pode se comportar como vetor:

● Portanto pode-se fazer coisas como:int a[10], *b;b = a;b[5] = 100;printf(“%d\n”, a[5]);printf(“%d\n”, b[5]);

int a[10], *b;b = (int*) malloc(10*sizeof(int));b[5] = 100;printf(“%d\n”, a[5]);printf(“%d\n”, b[5]);

100100

Page 22: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 22

Pergunta que não quer calar...

● int *a não é a declaração de um vetor de int?

● Em C, todo apontador pode se comportar como vetor:

● Portanto pode-se fazer coisas como:int a[10], *b;b = a;b[5] = 100;printf(“%d\n”, a[5]);printf(“%d\n”, b[5]);

int a[10], *b;b = (int*) malloc(10*sizeof(int));b[5] = 100;printf(“%d\n”, a[5]);printf(“%d\n”, b[5]);

100100

42657100

Obs: Não se pode fazer a = bno exemplo acima

Page 23: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 23

Apontadores para Tipos Estruturados

● Apontadores são normalmente utilizados com tipos estruturados

typedef struct{ int idade; double salario;}TRegistro;

TRegistro *a;...a = (TRegistro*) malloc( sizeof(TRegistro) )a->idade = 30; /* (*a).idade = 30 */a->salario = 80.0;

Page 24: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 24

Passagem de Parâmetros

● Em pascal, parâmetros para função podem ser passados por valor ou por referência

– Por valor: o parâmetro formal (recebido no procedimento) é uma cópia do parâmetro real (passado na chamada)

– Por referência: o parâmetro formal (recebido no procedimento) é uma referência para o parâmetro real (passado na chamada)

● Usa-se o termo var precedendo o parâmetro formal

● Em C só existe passagem por valor, logo deve-se implementar a passagem por referência utilizando-se apontadores

Page 25: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 25

Passagem de Parâmetros (C)

void soma_um(int x, int *y){ x = x+1; *y = (*y) +1; printf(“Funcao soma_um: %d %d\n”, x, *y);}

int main(){ int a = 0, b = 0; soma_um(a, &b); printf(“Programa principal: %d %d\n”, a, b);}

Page 26: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 26

Passagem de Parâmetros (C)

void soma_um(int x, int *y){ x = x+1; *y = (*y) +1; printf(“Funcao soma_um: %d %d\n”, x, *y);}

int main(){ int a = 0, b = 0; soma_um(a, &b); printf(“Programa principal: %d %d\n”, a, b);}

1 1

Page 27: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 27

Passagem de Parâmetros (C)

void soma_um(int x, int *y){ x = x+1; *y = (*y) +1; printf(“Funcao soma_um: %d %d\n”, x, *y);}

int main(){ int a = 0, b = 0; soma_um(a, &b); printf(“Programa principal: %d %d\n”, a, b);}

1 1

0 1

Page 28: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 28

Passagem de Parâmetros

● E para alocar memória dentro de um procedimento?

– Em pascal, basta passar a variável (apontador) como referência.

– Em C também, mas como não há passagem por referência as coisas são um pouco mais complicadas

void aloca(int* x, int n){ x = (int*) malloc(n*sizeof(int)); x[0] = 20;}

int main(){ int* a; aloca(a, 10); a[1] = 40;}

Error!Access Violation!

Page 29: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 29

Passagem de Parâmetros

● E para alocar memória dentro de um procedimento?

– Em pascal, basta passar a variável (apontador) como referência.

– Em C também, mas como não há passagem por referência as coisas são um pouco mais complicadas

void aloca(int* x, int n){ x = (int*) malloc(n*sizeof(int)); x[0] = 20;}

int main(){ int* a; aloca(a, 10); a[1] = 40;}

void aloca(int** x, int n){ *x = (int*) malloc(n*sizeof(int)); *x[0] = 20;}

int main(){ int* a; aloca(&a, 10); a[1] = 40;}

Error!Access Violation! OK

Page 30: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 30

Exercício

1) Faça um programa que leia um valor n, crie dinamicamente um vetor de n elementos e passe esse vetor para uma função que vai ler os elementos desse vetor.

2) Declare um TipoRegistro, com campos a inteiro e b que é um apontador para char. No seu programa crie dinamicamente uma váriavel do TipoRegistro e atribua os valores 10 e ‘x’ aos seus campos.

Page 31: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 31

Respostas (1)

void le_vetor(int* a, int n){ int i; for(i=0; i<n; i++) scanf("%d",&a[i]);}

int main(int argc, char *argv[]) { int *v, n, i; scanf("%d",&n); v = (int*) malloc(n*sizeof(int)); le_vetor(v, n); for(i=0; i<n; i++) printf("%d\n",v[i]);}

Apesar do conteúdo ser modificadoNão é necessário passar porreferência pois todo vetor jáé um apontador

Page 32: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 32

Respostas (2)

typedef struct { int a; char* b;}Tregistro;

int main(int argc, char *argv[]){ TRegistro *reg; reg = (TRegistro *) malloc(sizeof(TRegistro)); reg->a = 10; reg->b = (char *) malloc(sizeof(char)); *(reg->b) = 'x'; printf("%d %c",reg->a, *(reg->b));}

É necessário alocar espaço parao registro e para o campo b.*(reg->b) representa o conteúdoda variável apontada por reg->

Page 33: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 33

calloc

● void* calloc (size_t num, size_t size);

– Allocate and zero-initialize array

– Allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all its bits to zero.

– The effective result is the allocation of a zero-initialized memory block of (num*size) bytes.

– If size is zero, the return value depends on the particular library implementation (it may or may not be a null pointer), but the returned pointer shall not be dereferenced.

● Parameters

– num - Number of elements to allocate.

– size - Size of each element.

● Return Value

– On success, a pointer to the memory block allocated by the function.

– The type of this pointer is always void*, which can be cast to the desired type of data pointer in order to be dereferenceable.

– If the function failed to allocate the requested block of memory, a null pointer is returned.

Page 34: Alocação Dinâmica de Memória€¦ · Bruno Hott 2 Alocação Estática x Dinâmica C: dois tipos de alocação de memória: Estática e Dinâmica Na alocação estática, o espaço

Bruno Hott 34

realloc

● void* realloc (void* ptr, size_t size);

– Reallocate memory block

– Changes the size of the memory block pointed to by ptr.

– The function may move the memory block to a new location (whose address is returned by the function).

– The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location. If the new size is larger, the value of the newly allocated portion is indeterminate.

– In case that ptr is a null pointer, the function behaves like malloc, assigning a new block of size bytes and returning a pointer to its beginning.

● Parameters

– ptr - Pointer to a memory block previously allocated with malloc, calloc or realloc.● Alternatively, this can be a null pointer, in which case a new block is allocated (as if malloc was called).

– size - New size for the memory block, in bytes.

● Return

– A pointer to the reallocated memory block, which may be either the same as ptr or a new location.

– The type of this pointer is void*, which can be cast to the desired type of data pointer in order to be dereferenceable.