Diferença entre alocação de memória estática e alocação de memória dinâmica


Respostas:


90

Existem três tipos de alocação - estática, automática e dinâmica.

Alocação estática significa que a memória para suas variáveis ​​é alocada quando o programa é iniciado. O tamanho é fixo quando o programa é criado. Ele se aplica a variáveis ​​globais, variáveis ​​de escopo de arquivo e variáveis ​​qualificadas com staticfunções internas definidas.

A alocação automática de memória ocorre para variáveis ​​(não estáticas) definidas dentro de funções e geralmente são armazenadas na pilha (embora o padrão C não exija que uma pilha seja usada). Você não precisa reservar memória extra para usá-los, mas, por outro lado, também tem controle limitado sobre a vida útil dessa memória. Ex: variáveis ​​automáticas em uma função só estão lá até que a função termine.

void func() {
    int i; /* `i` only exists during `func` */
}

A alocação de memória dinâmica é um pouco diferente. Agora você controla o tamanho exato e o tempo de vida desses locais de memória. Se você não o liberar, ocorrerá vazamentos de memória, o que pode causar o travamento do seu aplicativo, já que em algum momento o sistema não pode alocar mais memória.

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

No exemplo superior, a memória alocada ainda é válida e acessível, embora a função seja encerrada. Quando você terminar com a memória, você deve liberá-la:

free(mem);

2
Claro que você tem controle sobre a vida útil das variáveis ​​... você é quem decide o escopo, certo?
Luchian Grigore

Claro, mas não foi isso que eu quis dizer. Você não pode estender o tempo de vida das variáveis ​​para superar seu escopo. Mas talvez eu deva esclarecer isso em minha resposta. Obrigado
Constantinius

5
-1 Esta resposta está errada. Você confunde variáveis estáticas e automáticas .
brice,

2
Sua própria frase diz: " Alocação estática significa que a memória para suas variáveis ​​é alocada automaticamente " Isso está errado . Dê uma olhada no que a página de manual da libc do GNU tem a dizer sobre isso.
brice,

1
@EliBendersky Foi reformulado agora. Verifique se está correto agora.
Suraj Jain de

115

Esta é uma pergunta padrão da entrevista:

Alocação de memória dinâmica

É a memória alocada em tempo de execução usando calloc(), malloc()e amigos. Às vezes também é referido como memória 'heap', embora não tenha nada a ver com a referência da estrutura de dados heap .

int * a = malloc(sizeof(int));

A memória heap é persistente até que free()seja chamada. Em outras palavras, você controla o tempo de vida da variável.

Alocação automática de memória

Isso é comumente conhecido como memória de 'pilha' e é alocado quando você entra em um novo escopo (geralmente quando uma nova função é colocada na pilha de chamadas). Depois que você sai do escopo, os valores dos endereços de memória automáticos são indefinidos e é um erro acessá-los .

int a = 43;

Observe que o escopo não significa necessariamente função. Os escopos podem ser aninhados em uma função, e a variável estará no escopo apenas dentro do bloco em que foi declarada. Observe também que o local onde essa memória é alocada não é especificado. (Em um sistema lógico , ele estará na pilha ou nos registros para otimização)

Alocação de memória estática

É alocado em tempo de compilação * e o tempo de vida de uma variável na memória estática é o tempo de vida do programa .

Em C, a memória estática pode ser alocada usando a staticpalavra - chave. O escopo é apenas a unidade de compilação.

As coisas ficam mais interessantes quando a externpalavra-chave é considerada . Quando uma externvariável é definida, o compilador aloca memória para ela. Quando uma externvariável é declarada , o compilador requer que a variável seja definida em outro lugar. A falha em declarar / definir externvariáveis ​​causará problemas de ligação, enquanto a falha em declarar / definir staticvariáveis ​​causará problemas de compilação.

no escopo do arquivo, a palavra-chave estática é opcional (fora de uma função):

int a = 32;

Mas não no escopo da função (dentro de uma função):

static int a = 32;

Tecnicamente, externe staticsão duas classes separadas de variáveis ​​em C.

extern int a; /* Declaration */
int a; /* Definition */

* Notas sobre alocação de memória estática

É um tanto confuso dizer que a memória estática é alocada em tempo de compilação, especialmente se começarmos a considerar que a máquina de compilação e a máquina host podem não ser a mesma ou podem nem estar na mesma arquitetura.

Pode ser melhor pensar que a alocação de memória estática é tratada pelo compilador ao invés de alocada em tempo de compilação .

Por exemplo, o compilador pode criar uma grande dataseção no binário compilado e quando o programa é carregado na memória, o endereço dentro dodatasegmento do programa será usado como o local da memória alocada. Isso tem a desvantagem de tornar o binário compilado muito grande se usar muita memória estática. É possível escrever um binário de vários gigabytes gerado a partir de menos de meia dúzia de linhas de código. Outra opção é o compilador injetar código de inicialização que alocará memória de alguma outra maneira antes de o programa ser executado. Este código irá variar de acordo com a plataforma de destino e sistema operacional. Na prática, os compiladores modernos usam heurísticas para decidir qual dessas opções usar. Você pode tentar fazer isso escrevendo um pequeno programa C que aloca uma grande matriz estática de itens de 10k, 1m, 10m, 100m, 1G ou 10G. Para muitos compiladores, o tamanho binário continuará crescendo linearmente com o tamanho da matriz, e após um certo ponto,

Registrar memória

A última classe de memória são variáveis ​​de 'registro'. Como esperado, as variáveis ​​de registro devem ser alocadas em um registro da CPU, mas a decisão na verdade é deixada para o compilador. Você não pode transformar uma variável de registro em uma referência usando o endereço de.

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

A maioria dos compiladores modernos é mais inteligente do que você para escolher quais variáveis ​​devem ser colocadas nos registros :)

Referências:


3
Nota: Em int * a = malloc(sizeof(*a));vez disso, sugiro evitar a repetição do tipo de a. Isso torna as coisas muito mais fáceis se alguma vez o tipo de amudança.
Shahbaz

1
Acidentalmente, é chamado de heap, mas não tem nada a ver com a estrutura de dados do heap. Pilha, neste caso, significa um lugar bagunçado
dinâmico

2
"Alocação de memória estática ... é alocada em tempo de compilação" Você quer dizer que o tamanho da alocação é determinado em tempo de compilação? A reserva de memória não aconteceria apenas em tempo de execução?
lf215

2

Alocação de memória estática: O compilador aloca o espaço de memória necessário para uma variável declarada. Usando o endereço do operador, o endereço reservado é obtido e este endereço pode ser atribuído a uma variável de ponteiro. Visto que a maioria das variáveis ​​declaradas tem memória estática, este A maneira de atribuir valor de ponteiro a uma variável de ponteiro é conhecida como alocação de memória estática. a memória é atribuída durante o tempo de compilação.

Alocação de memória dinâmica: usa funções como malloc () ou calloc () para obter memória dinamicamente. Se essas funções forem usadas para obter memória dinamicamente e os valores retornados por essas funções forem atribuídos a variáveis ​​de ponteiro, essas atribuições serão conhecidas como memória dinâmica alocação.memória é atribuída durante o tempo de execução.


2

Alocação de memória estática:

  • Variáveis ​​são alocadas permanentemente
  • A alocação é feita antes da execução do programa
  • Ele usa a estrutura de dados chamada pilha para implementar a alocação estática
  • Menos eficiente
  • Não há capacidade de reutilização de memória

Alocação de memória dinâmica:

  • As variáveis ​​são alocadas apenas se a unidade do programa ficar ativa
  • A alocação é feita durante a execução do programa
  • Ele usa a estrutura de dados chamada heap para implementar a alocação dinâmica
  • Mais eficiente
  • Existe capacidade de reutilização da memória . A memória pode ser liberada quando não for necessária

1
"Alocação de memória estática [...] usa a estrutura de dados chamada pilha para implementar a alocação estática" Não , isso é incorreto e enganoso. por favor, veja meu post para a diferença entre alocação automática e estática. A memória estática pode usar a pilha. Isso depende fortemente da implementação e várias estratégias podem ser usadas para a mesma implementação. Também não tenho certeza do que você entende por "menos eficiente". @Trieu Toan, você mudou o significado desta resposta com uma edição ruim.
brice

1

Diferença entre ALOCAÇÃO DE MEMÓRIA ESTÁTICA e ALOCAÇÃO DE MEMÓRIA DINÂMICA

A memória é alocada antes do início da execução do programa (durante a compilação).
A memória é alocada durante a execução do programa.

Nenhuma alocação de memória ou ações de desalocação são realizadas durante a execução.
As ligações de memória são estabelecidas e destruídas durante a execução.

As variáveis ​​permanecem alocadas de forma permanente.
Alocado apenas quando a unidade de programa está ativa.

Implementado usando pilhas e pilhas.
Implementado usando segmentos de dados.

O ponteiro é necessário para acessar as variáveis.
Não há necessidade de ponteiros alocados dinamicamente.

Execução mais rápida do que dinâmica.
Execução mais lenta do que estática.

Mais espaço de memória necessário.
Menos espaço de memória necessário.


1
alocação de memória estática é alocada na pilha, enquanto a alocação de memória dinâmica é alocada no heap
Usman Kurd

@UsmanKurd Isso geralmente é incorreto em relação à memória estática. Veja minha resposta.
brice

0

A alocação de memória estática é a memória alocada antes da execução do programa pf durante o tempo de compilação. A alocação de memória dinâmica é a memória alocada durante a execução do programa em tempo de execução.


-1

Alocação de memória estática. A memória alocada ficará na pilha.

int a[10];

Alocação de memória dinâmica. A memória alocada ficará no heap.

int *a = malloc(sizeof(int) * 10);

e este último deve ser livre d, uma vez que não há Garbage Collector (GC) em C.

free(a);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.