Mudanças entre as edições de "AULA 19 - Programação 1 - Graduação"
(7 revisões intermediárias pelo mesmo usuário não estão sendo mostradas) | |||
Linha 37: | Linha 37: | ||
*[http://www.cplusplus.com/reference/cstdlib/free/?kw=free free]: libera memória; | *[http://www.cplusplus.com/reference/cstdlib/free/?kw=free free]: libera memória; | ||
*[http://www.cplusplus.com/reference/cstdlib/realloc/ realloc]: realoca memória | *[http://www.cplusplus.com/reference/cstdlib/realloc/ realloc]: realoca memória | ||
− | *[http://pt.wikipedia.org/wiki/Calloc calloc]: | + | *[http://pt.wikipedia.org/wiki/Calloc calloc]: aloca n bytes de memória e zera. |
http://www.linuxjournal.com/article/4681 | http://www.linuxjournal.com/article/4681 | ||
Linha 64: | Linha 64: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ;EXEMPLO 2: Vejamos comos diferentes elementos do programa são armazenados quando esse programa é executado. Os comentários no código explicam onde as variáveis ficam armazenadas. | + | ;EXEMPLO 2: Diferente da função '''malloc''', '''calloc''' além de inicializar os espaços de memória ainda atribui o valor 0 (zero) para cada um deles. |
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main(void){ | ||
+ | |||
+ | int *valores, *aux; | ||
+ | int qtd, i, vlr; | ||
+ | |||
+ | printf("\nEntre com a quantidade de números: "); | ||
+ | scanf("%d", &qtd); | ||
+ | |||
+ | if(qtd == 0) | ||
+ | exit(0); | ||
+ | |||
+ | //Aloca um vetor com a quantidade recebida em qtd | ||
+ | valores = (int *) calloc(qtd, sizeof (int)); | ||
+ | |||
+ | //Imprime o endereco e valor (zero) para a quantidade de números informada | ||
+ | aux = valores; | ||
+ | for(i = 1; i <= qtd; i++){ | ||
+ | printf("%p\t%d\n", aux, *aux); | ||
+ | aux++; | ||
+ | } | ||
+ | |||
+ | aux = valores; //Ponteiro para o primeiro espaço de memória | ||
+ | for(i = 1; i <= qtd; i++){ | ||
+ | printf("Digite o número %d ->: ", i); | ||
+ | scanf("%d", &vlr); | ||
+ | *aux = vlr; | ||
+ | aux++; | ||
+ | } | ||
+ | |||
+ | aux = valores; //Retorna à posição inicial no mapa de memória | ||
+ | for(i = 1; i <= qtd; i++){ | ||
+ | printf("%p\t%d\n", aux, *aux); | ||
+ | aux++; | ||
+ | } | ||
+ | |||
+ | free(valores); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
+ | ;EXEMPLO 3: Vejamos comos diferentes elementos do programa são armazenados quando esse programa é executado. Os comentários no código explicam onde as variáveis ficam armazenadas. | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
Linha 89: | Linha 138: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Há várias ferramentas para verificar onde uma variável é armazenada na memória. Mas a ferramenta fácil de usar é '''nm'''. | + | ===Usando a ferramenta '''nm'''=== |
+ | Há várias ferramentas para verificar onde uma variável é armazenada na memória. Mas a ferramenta fácil de usar é '''nm'''. Compile o programa acima (EXEMPLO 2) como indicado abaixo: | ||
;Usando a ferramenta nm | ;Usando a ferramenta nm | ||
Linha 143: | Linha 193: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Os números são os valores de símbolo seguido do tipo de símbolo (apresentado como uma letra) e o nome do símbolo. | + | Os números são os valores de um símbolo, seguido do tipo de símbolo (apresentado como uma letra) e o nome do símbolo. |
− | + | O tipo de símbolo requer mais explicações: Uma letra '''minúsculas''' significa que é '''variável local''' e '''maiúsculas''' significa '''global''' (externamente disponíveis a partir do arquivo). | |
− | O tipo de símbolo requer mais explicações | + | :B Seção de dados não inicializados (BSS) |
− | B Seção de dados não inicializados (BSS) | + | :D Seção de dados inicializados |
− | D Seção de dados inicializados | + | :T Seção de texto/código |
− | T Seção de texto/código | + | :U não identificado |
− | U não identificado | ||
==Alocando uma estrutura == | ==Alocando uma estrutura == | ||
Linha 256: | Linha 305: | ||
! style="background: #cdc5bf;" | [[AULA 18 - Programação 1 - Graduação | << ]] | ! style="background: #cdc5bf;" | [[AULA 18 - Programação 1 - Graduação | << ]] | ||
! style="background: #cdc5bf;" | Aula 19 | ! style="background: #cdc5bf;" | Aula 19 | ||
− | ! style="background: #cdc5bf;" | [[ | + | ! style="background: #cdc5bf;" | [[AULA 20 - Programação 1 - Graduação | >> ]] |
|} | |} |
Edição atual tal como às 10h07min de 26 de maio de 2015
Alocação Dinâmica de Memória
Objetivos
- Anatomia de um programa em execução;
- Alocação dinâmica de memória.
A área de heap e o layout de memória de um programa C
Neste link podemos ter uma ideia da anatomia de um programa na memória do computador.
http://shivacherukuri.blogspot.com.br/2011/03/memory-layout-in-cdata-segmentbss-code.html
Podemos observar que existe as seguintes áreas:
- TEXT: área onde está o código;
- BSS: dados estaticamente alocados e não inicializados;
- DATA: dados estaticamente alocados e inicializados;
- STACK: área de pilha (variáveis locais);
- HEAP: área de dados alocados dinamicamente.
Quando declaramos uma variável global da forma:
int x;
a variável x é alocada em uma área chamada BSS (dados não incializados). Note que x possui uma área de memória reservada a ela (4 bytes) e cuja existência é o tempo de vida do programa em execução.
Da mesma forma, uma variável global da forma:
int y=10;
é alocada na área de DATA. A inicialização é definida normalmente na carga do programa. Os valores de inicialização são copiados para a área de DATA na carga do programa, a partir do arquivo executável.
Por vezes, o tamanho dos dados não são conhecidos antes da execução do programa. Neste caso, pode ser interessante criá-los dinamicamente e é neste ponto que entra a área de HEAP. Trata-se de uma área de memória, gerenciada a partir de funções da biblioteca do C.
As funções mais conhecidas são (http://en.wikipedia.org/wiki/C_dynamic_memory_allocation):
- malloc: aloca n bytes de memória;
- free: libera memória;
- realloc: realoca memória
- calloc: aloca n bytes de memória e zera.
http://www.linuxjournal.com/article/4681 http://www.cs.cmu.edu/~guna/15-123S11/Lectures/Lecture08.pdf
- EXEMPLO 1
- Alocação dinâmica de números inteiros (exercício puramente didático):
#include <stdlib.h>
main()
{
int *px, *py;
int resultado;
px = (int *) malloc(sizeof(int));
*px = 5;
py = (int *) malloc(sizeof(int));
*py = 2;
resultado = *px + *py;
free (px);
px = NULL;
free (py);
py = NULL;
}
- EXEMPLO 2
- Diferente da função malloc, calloc além de inicializar os espaços de memória ainda atribui o valor 0 (zero) para cada um deles.
#include <stdio.h>
#include <stdlib.h>
int main(void){
int *valores, *aux;
int qtd, i, vlr;
printf("\nEntre com a quantidade de números: ");
scanf("%d", &qtd);
if(qtd == 0)
exit(0);
//Aloca um vetor com a quantidade recebida em qtd
valores = (int *) calloc(qtd, sizeof (int));
//Imprime o endereco e valor (zero) para a quantidade de números informada
aux = valores;
for(i = 1; i <= qtd; i++){
printf("%p\t%d\n", aux, *aux);
aux++;
}
aux = valores; //Ponteiro para o primeiro espaço de memória
for(i = 1; i <= qtd; i++){
printf("Digite o número %d ->: ", i);
scanf("%d", &vlr);
*aux = vlr;
aux++;
}
aux = valores; //Retorna à posição inicial no mapa de memória
for(i = 1; i <= qtd; i++){
printf("%p\t%d\n", aux, *aux);
aux++;
}
free(valores);
return 0;
}
- EXEMPLO 3
- Vejamos comos diferentes elementos do programa são armazenados quando esse programa é executado. Os comentários no código explicam onde as variáveis ficam armazenadas.
int bss1;
static double bss2;
char *bss3;
// estas variáveis são armazenadas no segmento de dados não inicializado (BSS)
int init1=0;
float init2=10.0;
char *init3="Alo mundo!";
// estas variáveis são armazenadas no segmento de dados inicializados (DATA)
// o código para função principal é armazenado em (code segment)
int main()
{
int local1=10; // esta variável é armazenada na pilha (stack) e código de inicialização é gerado pelo compilador.
int local2; //esta variável não é inicializada, portanto, tem valor de lixo. Ela não fica inicializada com zero.
static int local3; // esta é alocada no segmento BSS e é inicializada com zero.
static int local4=100; //este é alocada e inicializada no segmento de dados
int *local5=malloc(sizeof(int));
// esta variável é alocada na pilha no entanto, aponta para onde é alocada dinamicamente pelo bloco no heap.
return 0;
// stack frame para a função principal é destruída depois de executado o programa principal.
}
Usando a ferramenta nm
Há várias ferramentas para verificar onde uma variável é armazenada na memória. Mas a ferramenta fácil de usar é nm. Compile o programa acima (EXEMPLO 2) como indicado abaixo:
- Usando a ferramenta nm
- $ gcc codigo.c -o teste
- $ nm ./teste
Se nenhum argumento for passado para nm, o programa assume a entrada como a.out e vamos obter alguma saída como abaixo.
08049f28 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484dc R _IO_stdin_used
w _Jv_RegisterClasses
08049f18 d __CTOR_END__
08049f14 d __CTOR_LIST__
08049f20 D __DTOR_END__
08049f1c d __DTOR_LIST__
080485e0 r __FRAME_END__
08049f24 d __JCR_END__
08049f24 d __JCR_LIST__
0804a020 A __bss_start
0804a00c D __data_start
08048490 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_handle
w __gmon_start__
08048482 T __i686.get_pc_thunk.bx
08049f14 d __init_array_end
08049f14 d __init_array_start
08048480 T __libc_csu_fini
08048410 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804a020 A _edata
0804a044 A _end
080484bc T _fini
080484d8 R _fp_hw
080482b4 T _init
08048330 T _start
0804a040 B bss1
0804a030 b bss2
0804a03c B bss3
0804a020 b completed.6159
0804a00c W data_start
0804a024 b dtor_idx.6161
080483c0 t frame_dummy
0804a028 B init1
0804a014 D init2
0804a018 D init3
0804a038 b local3.1236
0804a01c d local4.1237
080483e4 T main
U malloc@@GLIBC_2.0
</syntaxhighlight>
Os números são os valores de um símbolo, seguido do tipo de símbolo (apresentado como uma letra) e o nome do símbolo.
O tipo de símbolo requer mais explicações: Uma letra minúsculas significa que é variável local e maiúsculas significa global (externamente disponíveis a partir do arquivo).
- B Seção de dados não inicializados (BSS)
- D Seção de dados inicializados
- T Seção de texto/código
- U não identificado
Alocando uma estrutura
#include <stdio.h>
#include <stdlib.h>
void main()
{
struct TTeste{
int x;
int y;
};
struct TTeste *teste;
teste = (struct TTeste *) malloc (sizeof(struct TTeste));
if (teste==NULL) {
printf("erro de alocação");
exit(1);
}
teste->x=10;
free(teste);
teste=NULL;
}
Usando o typedef para ajudar na definição e declaração de estruturas
#include <stdio.h>
#include <stdlib.h>
void main()
{
typedef struct {
int x;
int y;
} TTeste;
TTeste *teste;
teste = (TTeste *) malloc (sizeof(TTeste));
if (teste==NULL) {
printf("erro de alocação");
exit(1);
}
teste->x=10;
free(teste);
teste=NULL;
}
Alocando dinamicamente uma tabela de estruturas
#include <stdio.h>
#include <stdlib.h>
void main()
{
struct TTeste{
int x;
int y;
} *teste;
if ((teste = (struct TTeste *) malloc (100*sizeof(struct TTeste)))==NULL) {
printf("erro de alocação");
exit(1);
}
teste[10].x= 5;
if ((teste = realloc(teste, 10000*sizeof(struct TTeste)))==NULL) {
printf("erro de alocação");
exit(1);
}
teste[9000].x=20;
free(teste);
}
- EXERCÍCIO
- Refazer o exemplo anterior para que a quantidade de memória a ser alocada pela tabela seja passada na linha de comando.
<<
Aula 19
>>