Na verdade, isso está relacionado à pergunta que fiz ontem sobre por que tanto uma pilha quanto uma pilha são necessárias nos aplicativos que usamos hoje (e por que não podemos simplesmente usar uma pilha em vez de ambas, para ter um & padrão singular a seguir).
No entanto, muitas das respostas indicaram que uma pilha é insubstituível devido ao fato de ser muitas centenas (ou milhares) de vezes mais rápida do que tentar alocar / referenciar a pilha. Sei que há um problema com a alocação dinâmica de armazenamento se acabarmos com o Heap, mas não há uma maneira de contornar isso, ou talvez, uma maneira de melhorar a pilha para que ele possa lidar com a alocação dinâmica de memória?
Respostas:
O problema com as pilhas é que você não pode "liberar" a memória, a menos que esteja no topo da pilha. Por exemplo, digamos que você alocou três itens de tamanhos variados:
A pilha teria
a
no fundo,b
no meio ec
no topo. Isso se torna problemático se queremos liberarb
:A solução alternativa é mover todos os dados depois
b
e mudar se for o casoa
. Isso funciona, mas exigirá 5000000 cópias neste caso - algo que será muito mais lento que um monte.É por isso que temos um monte. Embora a alocação possa ser mais lenta que uma pilha (
O(log n)
vsO(1)
), as pilhas permitem que a liberação de memória em um local arbitrário seja rápida - emO(log n)
comparação com a pilhaO(n)
fonte
Facebook doesn't remove content from its disk when you ask it to remove it, it just removes the pointer to it
- O que é basicamente o que acontece quando você exclui um arquivo de qualquer sistema operacional.Pilha é por thread, Heap é todo o processo
Se houver 100 threads em todos os itens de trabalho que eu coloquei em uma fila, exatamente onde aloco os itens de trabalho para que qualquer um dos 100 threads os veja?
Existem outros tipos de memória também
Por exemplo, arquivos mapeados na memória, memória compartilhada, E / S mapeada (modo kernel). O argumento da eficiência é meio discutível nessas situações.
fonte
Uma pilha é uma estrutura LIFO (último a entrar, primeiro a sair), na parte superior da qual é mantido um ponteiro de referência (geralmente suportado por hardware). Dito isto, qualquer coisa que você está tentando alocar na pilha em vez da pilha teria que ser uma variável local em todas as funções, no topo dessa pilha. Portanto, o principal motivo contra uma pilha é que sua rotina main () precisaria pré-alocar todas as estruturas de dados que seu programa usa (que se destinam a permanecer durante toda a duração do seu programa) antecipadamente, como todas as estruturas de dados alocadas as chamadas de função serão removidas quando as chamadas de função retornarem e seus quadros ou registros de ativação forem removidos da pilha.
fonte
As pilhas funcionam muito bem para alocações de memória que obedecem às regras LIFO (Last in First Out), ou seja, você libera a memória na ordem inversa exata que a aloca. O LIFO é um padrão de alocação de memória muito comum, talvez o mais comum. Mas não é o único padrão, ou mesmo o único padrão comum. Para escrever um programa eficiente que possa lidar com uma ampla variedade de problemas, precisamos levar em consideração os padrões menos comuns, mesmo que isso signifique uma infra-estrutura mais complexa.
Se eu conseguir todas as meta para um parágrafo: você é iniciante, como iniciante valoriza a simplicidade e as regras em preto e branco. No entanto, como iniciante, você tem apenas uma visão geral da variedade de problemas e restrições que precisam ser acomodados por programas de computador. Você está inserindo uma tecnologia que está em desenvolvimento ativo há 75 anos. Não há nada de errado em perguntar por que as coisas são do jeito que são, mas a resposta geralmente será "Sim, tentamos o método simples e direto há 50 anos e acabou por não funcionar muito bem para aulas inteiras. de problemas, então tivemos que fazer algo mais complicado ". À medida que a tecnologia avança, a simplicidade geralmente tem que dar lugar à eficiência e flexibilidade.
fonte
Por outro exemplo, fechamentos. Se você empilhar pop, poderá perder o registro de ativação do seu fechamento. Portanto, se você deseja que a função anônima e seus dados persistam, você deve armazená-la em outro lugar que não seja a pilha de tempo de execução.
fonte
Entre muitos outros motivos para alocar armazenamento de heap.
Se você deseja passar o endereço de um objeto de volta para um programa de chamada, não deve passar o endereço de uma variável da pilha, pois o armazenamento da pilha será reutilizado e possivelmente substituído pela próxima função chamada. Você precisa obter o armazenamento necessário usando malloc () para garantir que ele não seja sobrescrito por chamadas para funções subseqüentes.
Você pode passar endereços de itens de pilha de sua função para funções que você chama, porque você pode garantir que elas existam até que seu programa "retorne ()". Mas assim que sua função retornar, todo o armazenamento da pilha estará disponível.
fonte