1 / 30

Estruturas de Dados - T.332 Capítulo 3 Parte 2: Alocação Dinâmica de Memória

Estruturas de Dados - T.332 Capítulo 3 Parte 2: Alocação Dinâmica de Memória. 3.1 As Funções de Alocação Dinâmica de Memória em "C". Já visto até agora: Constantes são " codificadas " dentro do código objeto de um programa em tempo de compilação.

donkor
Download Presentation

Estruturas de Dados - T.332 Capítulo 3 Parte 2: Alocação Dinâmica de Memória

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Estruturas de Dados - T.332Capítulo 3Parte 2:Alocação Dinâmica de Memória

  2. 3.1 As Funções de Alocação Dinâmica de Memória em "C" • Já visto até agora: • Constantes são "codificadas" dentro do código objeto de um programa em tempo de compilação. • Variáveis globais (estáticas) têm a sua alocação codificada em tempo de compilação e são alocadas logo que um programa inicia a execução. • Variáveis locais em funções (ou métodos) são alocadas através da requisição de espaço na pilha (stack). Alocação Dinâmica é um meio pelo qual o programa pode obter memória enquanto está em execução.

  3. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } Topo da Memória StackPointer Inicio da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  4. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } Topo da Memória StackPointer Topo da Pilha HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  5. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  6. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  7. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB &func_B-#2 local1 local2 HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  8. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB &func_B-#2 local1 local2 HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  9. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  10. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB &func_B-#3 local1 local2 HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  11. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB &func_B-#2 local1 local2 HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  12. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } StackPointer Topo da Pilha Topo da Memória &main-#3 localA localB HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  13. Programa: • #include <stdio.h> • char *a = "Essa aula é legal”; • char *b = "Será mesmo?"; • int func_A () • { • int local1, local2; • - - - • } • void func_B () • { • int localA, localB; • localA = func_A(); • localB = func_A(); • } • main () • { • func_B(); • } Topo da Memória StackPointer Topo da Pilha HeapPointer Topo da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sist.Operacional Base da Memória

  14. Alocação Dinâmica em "C" • A memória alocada pelas funções de alocação dinâmica é obtida do heap. • O heap é a região de memória livre que se encontra entre o programa (com a área de armazenamento permanente) e a pilha (stack). • O tamanho do heap é, a princípio, desconhecido do programa. • "C" possui duas funções básicas para gerência de memória: • malloc(nº de bytes) - aloca memória. • free(endereço) - libera memória

  15. Função malloc: • Protótipo: void *malloc(size_t número_de_bytes); • Detalhes : • Devolve um ponteiro do tipo void (sem tipo) para o início da área de memória alocada. • Isto significa que o valor deste ponteiro pode ser atribuído a qualquer variável do tipo ponteiro. • número_de_bytes é a quantidade de bytes a ser alocada. • Se a memória for alocada no topo do heap, o heapPointer é atualizado (incrementado de número_de_bytes). • O tipo size_t é definido em stdlib.h que deve ser sempre incluído no início de um programa usando alocação dinâmica.

  16. Exemplo: • #include <stdio.h> • #include <stdlib.h> • char *p; • int *q; • main () • { • p = malloc(1000); • // Aloca 1000 • // bytes de RAM • q = malloc(50*sizeof(int)); • // Aloca espaço • // para 50 inteiros. • } HeapPointer Topo da Área Alocável Topo da Memória StackPointer Topo da Pilha 50*int = 200 bytes 1000 bytes p q Variáveis estáticas 10010101... Código objeto Constantes Sist.Operacional Base da Memória

  17. malloc devolve: • um ponteiro para a área alocada • o ponteiro nulo (NULL) caso não seja possível alocar a memória requisitada. • Convém verificar se foi pos-sível alocar a memória: • #include <stdio.h> • #include <stdlib.h> • char *p; • main () • { ................ • p = malloc(1000) • // Tenta alocar 1000 • // bytes de RAM • if (p == NULL) • // Testa se p • // diferente de 0 • printf("Sem memória."); • } Topo da Memória Espaço de variáveis locais alocado StackPointer Topo da Pilha HeapPointer Topo da Área Alocável Já alocado antes p Variáveis estáticas 10010101... Código objeto "Sem memória" Constantes Sist.Operacional Base da Memória

  18. Função free: • Protótipo: void free( void *p ); • Detalhes : • Devolve memória previamente alocada ao sistema. • A memória devolvida é aquela que foi alocada com um ponteiro com o valor de p. • O valor de pdeve obrigatoriamente ser um valor que foi alguma vez retornado por malloc(). • Não é possível alocar-se um vetor enorme e depois dealocar-se a parte dele que "sobrou". • A utilização de free() com um valor de ponteiro qualquer poder ter resultados catastróficos. • A gerência de buracos no heap é responsabilidade do sistema operacional.

  19. Exercício (agora): Lista Ordenada com um vetor de ponteiros para Strings. • Uma lista ordenada pode conter Strings de qualquer comprimento < 10000. • Esta lista tem número de elementos máximo fixo = 100 e é implementada como um vetor de ponteiros para Strings. • Um novo String é lido primeiramente para dentro de uma variável auxiliar qualquer. • Então é alocada memória para exatamente o seu tamanho e ele é copiado para esta área. Para copiar um String utilize strcopy. • Por fim um lugar na lista é encontrado para ele, através da atualização dos valores dos ponteiros da lista. • Como critério de ordenação basta somente a primeira letra do String.

  20. Topo da Memória StackPointer Topo da Pilha • Organização de memória do Exercício: Espaço de variáveis locais alocado HeapPointer Topo da Área Alocável str4 str3 str2 str1 Vetor de char* Var.Estáticas 10010101... Código objeto Constantes Sist.Operacional Base da Memória

  21. Para verificar o comprimento de um String: • Utilize a função strlen(). • Esta função devolve o comprimento (em caracteres imprimíveis) de um String. • Protótipo: int strlen(char *p); • #include <stdio.h> • #include <stdlib.h> • #include <sting.h> • char p[90] = "Carro"; • main () • { • printf("%i", strlen(p) ); • } • Imprime: 5.

  22. Para copiar um String: • Utilize a função strcpy(). • Esta função copia o conteúdo de um string (dado por um apontador) para a posição de memória dada por outro apontador. • Protótipo: char *strcpy(char *destino, *fonte); • #include <stdio.h> • #include <stdlib.h> • #include <sting.h> • char p[90] = "Carro"; • char lata[20]; • main () • { • strcpy(lata, p) ); • printf("s%", lata); • } • Imprime: Carro.

  23. Exemplo: Para ler um String: • Utilize a função scanf(formato, char1*, …, charn*). • Esta função copia o conteúdo digitado ate um separador para o primeiro ponteiro, depois para outro e assim por diante. • Utilize a função gets(char*). • Esta função le uma linha inteira, inclusive virgulas, espaços e outros para a posição de memória apontada por char*. • #include <stdio.h> • #include <sting.h> • char linha[1000]; • char estringue[20]; • main () • { • scanf(“%s”, estringue); /* le até um espaço ou • similar */ • getchar(); /* limpa o enter */ • gets(linha);/* lê tudo até o enter */ • }

  24. Detalhes: Lista Ordenada com um vetor de ponteiros para Strings. • Como você não sabe o comprimento do String que o usuário vai digitar, use primeiro uma variável auxiliar grande (10000 posições) para guardar o que foi digitado. • A lista deve ser passada como parâmetro para todas as funções que a utilizam. • Da mesma maneira as variáveis de controle da lista. • Todas as funções de lista ordenada implementadas anteriormente devem ser reimplementadas para utilizar estes Strings.

  25. Headerfile: Como Garantir Inclusão Única /* Arquivo: pilha.h */ #ifndef EstruturaDaPilha #define EstruturaDaPilha /* Definir uma estrutura para a pilha */ struct estruturaDaPilha { int topo; int dados[MaxPilha]; }; /* Def. um tipo que tem a estrutura da pilha. */ typedef struct estruturaDaPilha pilha; #endif

  26. Headerfiles: Importante • A diretiva de compilação #ifndef (if not defined) diz que aquela área de código fonte entre o #ifndef e o #endif somente será levada em conta pelo compilador se o argumento de #ifndef ainda não houver sido definido na mesma sessão de compilação no escopo de um módulo. • Isso garante que código que a gente "por via das duvidas" inclui mais de uma vez em um modulo não seja considerado duas vezes. • Um exemplo de como isto e útil esta na diretiva #include <stdio.h> que esta presente tanto em pilha.h como em pilha.c como em aplic.c. • Como aplic.c carrega pilha.h "para dentro" de si mesmo, carregara também stdio.h. Como está explicitamente também carregando stdio.h, se não houver uma diretiva #ifndef em stdio.h, ele terá o mesmo código existente em stdio.h duas vezes.

  27. Projetos de Implementação: Usando Make • Make: Utilitário que auxilia a compilação de projetos formados por vários arquivos de programas • Realiza checagem de dependências entre o arquivo destino e os fontes • Baseia-se nas datas de arquivos

  28. Projetos de Implementação: Sintaxe do Makefile aplic: aplic.o pilha.o gcc -g -o aplic aplic.o pilha.o aplic.o: aplic.c pilha.h gcc -g - c aplic.c pilha.o: pilha.c pilha.h gcc -g -c pilha.c meta: dependencia1 dependênciaN <tab>um comando para atingir meta <tab>outro comando para atingir meta

  29. Projetos de Implementação: Usando o Makefile • Chamada: make -f <nome do Makefile> • Se o nome não for dado, make procurará por arquivos chamados Makefile e makefile, nesta ordem. • Para definir qual meta será a primeira a ser considerada: • Se você não diz nada, a primeira meta será considerada. • Voce pode passar como último parâmetro o nome da meta: make -f meuMakefile compilar • Todas as dependencias de compilar, se esta meta existir, serão também levadas em consideração.

  30. Módulo lista.h: • #ifndef Lista • #define Lista • typedef struct estruLista { • char *elemento[30]; • int ultimo; • int max; • }; • typedef struct estruLista lista; • #endif • Módulo lista.c: • #include <stdio.h> • #include <stdlib.h> • #include “lista.h” • lista *criaLista () • { • lista *nova; • nova = malloc( sizeof(lista) ); • nova->max = 30; • nova->ultimo = -1; • return (nova); • } • void destroiLista(lista *morta) • { • // Libera memória p/os strings • for (i=0; morta->ultimo; i++) • free (morta->elemento[i]); • // Libera memória da lista • free ( morta ); • }

More Related