Ultimamente, quando eu estiver escrevendo C ou C ++, declararei todas as minhas variáveis na pilha apenas porque é uma opção, ao contrário do Java.
No entanto, ouvi dizer que é uma má idéia declarar coisas grandes na pilha.
- Por que exatamente é esse o caso? Eu acho que o estouro de pilha está envolvido, mas não sei muito bem por que isso acontece.
- Quanta coisa na pilha é demais?
Não estou tentando colocar arquivos de 100 MB na pilha, apenas uma dúzia de matrizes de kilobytes para usar como buffers de string ou qualquer outra coisa. Isso é muito uso de pilha?
(Desculpe, se duplicado, a busca por pilha continuava fornecendo referências ao estouro de pilha. Não há nem uma etiqueta de pilha de chamada, apenas usei a abstrata.)
stack
memory-usage
stackoverflow
Elliot Way
fonte
fonte
std::vector<int>
variável local não ocupa muito espaço na pilha, a maioria dos dados está no heap.Respostas:
Depende do seu sistema operacional. No Windows, o tamanho máximo típico para uma pilha é de 1 MB, enquanto é de 8 MB em um Linux moderno típico, embora esses valores sejam ajustáveis de várias maneiras. Se a soma de suas variáveis de pilha (incluindo despesas gerais de baixo nível, como endereços de retorno, argumentos baseados em pilha, espaços reservados para valores de retorno e bytes de alinhamento) em toda a pilha de chamadas exceder esse limite, você obterá um estouro de pilha, o que normalmente reduz o seu programa sem nenhuma chance de recuperação.
Alguns kilobytes geralmente são bons. Dezenas de kilobytes são perigosos porque começam a resumir. Centenas de kilobytes é uma péssima idéia.
fonte
$ ulimit -a
no meu sistema retorna entre outrosstack size (kbytes, -s) 8192
.A única resposta válida é vaga: "é demais quando a pilha transborda".
A menos que você tenha controle total sobre a implementação de todas as linhas de código entre o ponto de entrada do programa e a função em questão, não será possível fazer suposições sobre a quantidade de pilha disponível. Você não pode, por exemplo, garantir que a chamada dessa função nunca cause um estouro de pilha:
A pilha padrão de 8 MiB nos Unixes modernos tem bastante espaço para as pilhas, especialmente para alguém como eu, que é um velhote suficiente para se lembrar de CPUs com ponteiros de pilha de 8 bits. A realidade prática é que é improvável que você exploda isso sem tentar. Se o fizer, exceder o limite da pilha é geralmente considerado uma violação de segmentação, e sistemas com gerenciamento de memória suficiente para detectá-lo enviarão um
SIGSEGV
quando isso acontecer.Você tem algumas opções. Primeiro é não adivinhar quanta pilha está disponível e perguntar ao sistema. Qualquer coisa em conformidade com o POSIX terá uma
getrlimit(2)
função que informará o limite superior.RLIMIT_STACK
é o limite específico que você deseja. O segundo é monitorar a quantidade de pilha que seus programas estão usando e tomar decisões sobre variáveis automáticas versus alocação dinâmica de memória com base nisso. Até onde eu sei, não existem funções padrão para determinar quanto da pilha é usada, mas programas como ovalgrind
podem analisar por você.fonte
Se você alocar uma matriz de, digamos, 10.000 bytes na pilha, essa matriz é limitada em tamanho. 10.000 podem ser muito, mas se você precisar de 10.001 bytes, seu programa poderá falhar ou algo pior. Portanto, nessa situação, você deseja algo que se adapte ao tamanho necessário e que não esteja na pilha.
Matrizes de tamanho fixo para buffers de seqüência de caracteres na pilha não são um problema porque mantêm memória na pilha, são um problema porque os buffers de tamanho fixo são um problema fatal que está esperando para acontecer.
Mas se você usa C ++ e declara, por exemplo, um std :: string ou um std :: vec na pilha, o que está na pilha será realmente de tamanho fixo e pequeno. Os dados reais serão armazenados na pilha. Você pode armazenar um milhão de caracteres em uma instância std :: string, e apenas uma quantidade muito pequena de dados (geralmente de 8 a 24 bytes, dependendo da implementação) na pilha e um milhão de bytes no heap.
fonte
Bem, 1 MB é uma boa estimativa para * nix. A recursão pode ser um dos principais motivos para o estouro de pilha em combinação com as alocações de pilha. No entanto, na maioria dos casos, os objetos god que parecem superficialmente grandes demais para serem colocados na pilha são projetados bem para gerenciar sua memória interna na pilha e usar a pilha apenas como uma maneira de ser destruída automaticamente quando a pilha é exibida. O destruidor liberará os enormes pedaços de memória gerenciados internamente. Os contêineres std são projetados dessa maneira e os ponteiros compartilhados / exclusivos também.
O importante é não alocar grandes pedaços de mem bruto na pilha como char [1024 * 1024] e projetar classes para agrupar alocações de heap e usar a pilha apenas para a conveniência de chamar automaticamente o destruidor.
fonte