alloca()
aloca memória na pilha e não na pilha, como no caso de malloc()
. Então, quando eu volto da rotina, a memória é liberada. Então, na verdade, isso resolve meu problema de liberar memória alocada dinamicamente. A liberação de memória alocada malloc()
é uma grande dor de cabeça e, se perdida de alguma forma, leva a todos os tipos de problemas de memória.
Por que o uso de alloca()
desencorajado apesar dos recursos acima?
free
(o que é obviamente uma vantagem), a não capacidade de incorporá-lo (obviamente, as alocações de heap são muito mais pesadas) e etc. O único motivo a ser evitadoalloca
é o tamanho grande. Ou seja, desperdiçar toneladas de memória da pilha não é uma boa ideia, além de você ter a chance de um estouro de pilha. Se for esse o caso - considere usarmalloca
/freea
alloca
é que a pilha não pode ser fragmentada como a pilha. Isso pode ser útil para aplicativos de estilo duradouro em tempo real ou mesmo críticos para a segurança, uma vez que a WCRU pode ser analisada estaticamente sem recorrer a conjuntos de memória personalizados com seu próprio conjunto de problemas (sem localidade temporal, recurso insuficiente) usar).Respostas:
A resposta está aí na
man
página (pelo menos no Linux ):O que não quer dizer que nunca deva ser usado. Um dos projetos de OSS em que trabalho o usa extensivamente e, desde que você não esteja abusando (com
alloca
valores enormes), tudo bem. Depois de ultrapassar a marca "algumas centenas de bytes", é hora de usar osmalloc
amigos. Você ainda pode ter falhas de alocação, mas pelo menos terá alguma indicação da falha, em vez de apenas estourar a pilha.fonte
alloca()
não têm o mesmo medo de matrizes ou recursões locais (de fato, muitas pessoas que gritarãoalloca()
elogiarão a recursão porque "parece elegante") . Eu concordo com o conselho de Shaun ("alloca () é bom para pequenas alocações"), mas eu discordo da mentalidade de enquadrar alloca () como exclusivamente ruim entre os 3 - eles são igualmente perigosos!Um dos bugs mais memoráveis que tive foi o uso de uma função inline usada
alloca
. Ele se manifestou como um estouro de pilha (porque é alocado na pilha) em pontos aleatórios da execução do programa.No arquivo de cabeçalho:
No arquivo de implementação:
Então, o que aconteceu foi a
DoSomething
função incorporada do compilador e todas as alocações de pilha estavam acontecendo dentro daProcess()
função e, assim, explodindo a pilha. Em minha defesa (e não fui eu quem encontrou o problema; tive que chorar para um dos desenvolvedores seniores quando não consegui consertá-lo), não foi diretoalloca
, foi um dos conversores de string ATL macros.Portanto, a lição é - não use
alloca
em funções que você acha que podem estar embutidas.fonte
Pergunta antiga, mas ninguém mencionou que deveria ser substituída por matrizes de comprimento variável.
ao invés de
Está no padrão C99 e existia como extensão de compilador em muitos compiladores.
fonte
alloca () é muito útil se você não puder usar uma variável local padrão porque seu tamanho precisaria ser determinado em tempo de execução e você pode garantir absolutamente que o ponteiro obtido de alloca () NUNCA será usado após o retorno dessa função .
Você pode estar razoavelmente seguro se você
O perigo real vem da chance de alguém violar essas condições algum tempo depois. Com isso em mente, é ótimo para passar buffers para funções que formatam texto neles :)
fonte
alloca()
aloca memória que dura até o final da função. Isso significa que parece não haver tradução direta e conveniente para o VLA def() { char *p; if (c) { /* compute x */ p = alloca(x); } else { p = 0; } /* use p */ }
. Se você acha que é possível converter automaticamente usos dealloca
para usos de VLA, mas exige mais de um comentário para descrever como, eu posso fazer disso uma pergunta.Conforme observado nesta postagem do grupo de notícias , existem alguns motivos pelos quais o uso
alloca
pode ser considerado difícil e perigoso:alloca
.alloca
diferente, portanto, a portabilidade não é garantida, mesmo entre os compiladores que o suportam.fonte
alloca()
requer registros separados para manter o ponteiro de pilha e o ponteiro de quadro. Em CPUs x86> = 386, o ponteiro da pilhaESP
pode ser usado para ambos, liberandoEBP
- a menos quealloca()
seja usado.f(42, alloca(10), 43);
poderá travar devido à possibilidade de o ponteiro da pilha ser ajustadoalloca()
depois que pelo menos um dos argumentos for pressionado.Uma questão é que não é padrão, embora seja amplamente suportado. Sendo outras coisas iguais, eu sempre usaria uma função padrão em vez de uma extensão comum do compilador.
fonte
Não percebo tal consenso. Muitos profissionais fortes; alguns contras:
while
oufor
loop) ou em vários escopos, a memória se acumula por iteração / escopo e não é liberada até que a função saia: isso contrasta com as variáveis normais definidas no escopo de uma estrutura de controle (por exemplo,for {int i = 0; i < 2; ++i) { X }
acumularia aalloca
memória solicitada no X, mas a memória para uma matriz de tamanho fixo seria reciclada por iteração).inline
funcionam com a chamadaalloca
, mas se você forçá-los,alloca
isso acontecerá no contexto dos chamadores (ou seja, a pilha não será liberada até que o chamador retorne)alloca
migrou de um recurso / hack não portátil para uma extensão padronizada, mas alguma percepção negativa pode persistirmalloc
o controle explícitomalloc
incentiva o pensamento sobre a desalocação - se isso é gerenciado por meio de uma função de wrapper (por exemploWonderfulObject_DestructorFree(ptr)
), a função fornece um ponto para a implementação de operações de limpeza (como fechar descritores de arquivo, liberar ponteiros internos ou fazer log) sem alterações explícitas no cliente código: às vezes é um bom modelo para adotar de forma consistenteWonderfulObject* p = WonderfulObject_AllocConstructor();
- isso é possível quando o "construtor" é uma função que retornamalloc
memória (como a memória permanece alocada após a função retornar o valor a ser armazenadop
), mas não se o "construtor" usaralloca
WonderfulObject_AllocConstructor
poderia conseguir isso, mas "as macros são más", pois podem entrar em conflito entre si e com o código não macro e criar substituições não intencionais e consequentes problemas difíceis de diagnosticarfree
operações ausentes podem ser detectadas pelo ValGrind, Purify etc., mas as chamadas "destruidoras" ausentes nem sempre podem ser detectadas - um benefício muito tênue em termos de aplicação do uso pretendido; algumasalloca()
implementações (como as GCCs) usam uma macro embutida paraalloca()
, portanto, a substituição em tempo de execução de uma biblioteca de diagnóstico de uso de memória não é possível do jeito que é paramalloc
/realloc
/free
(por exemplo, cerca elétrica)Eu sei que essa pergunta está marcada como C, mas como programador de C ++, pensei em usar o C ++ para ilustrar a utilidade potencial de
alloca
: o código abaixo (e aqui na ideone ) cria um vetor que rastreia tipos polimórficos de tamanhos diferentes e com alocação de pilha (com tempo de vida vinculado ao retorno da função) em vez do heap alocado.fonte
Todas as outras respostas estão corretas. No entanto, se o que você deseja alocar
alloca()
é razoavelmente pequeno, acho que é uma boa técnica mais rápida e conveniente do que usarmalloc()
ou não.Em outras palavras,
alloca( 0x00ffffff )
é perigoso e provavelmente causa estouro, exatamente o quechar hugeArray[ 0x00ffffff ];
é. Seja cauteloso e razoável e você ficará bem.fonte
Muitas respostas interessantes para essa pergunta "antiga", até algumas respostas relativamente novas, mas não encontrei nenhuma que mencionasse isso ...
Encontrei essa citação em ... OK, fiz essa citação. Mas realmente, pense nisso ....
@j_random_hacker está muito certo em seus comentários sob outras respostas: Evitar o uso de a
alloca()
favor de matrizes locais superdimensionadas não torna seu programa mais seguro contra estouros de pilha (a menos que seu compilador tenha idade suficiente para permitir a inclusão de funções usadasalloca()
nesse caso, você deve atualização, ou a menos que você usealloca()
loops internos; nesse caso, você não deve ... usaralloca()
loops internos).Trabalhei em ambientes de desktop / servidor e sistemas embarcados. Muitos sistemas embarcados nem sequer usam um heap (eles nem se vinculam no suporte a ele), por motivos que incluem a percepção de que a memória alocada dinamicamente é ruim devido aos riscos de vazamento de memória em um aplicativo que nunca sempre reinicia por anos, ou a justificativa mais razoável de que a memória dinâmica é perigosa porque não se pode ter certeza de que um aplicativo nunca fragmentará sua pilha ao ponto de falsa exaustão de memória. Portanto, os programadores incorporados ficam com poucas alternativas.
alloca()
(ou VLAs) pode ser a ferramenta certa para o trabalho.Eu vi várias vezes em que um programador cria um buffer alocado para a pilha "grande o suficiente para lidar com qualquer caso possível". Em uma árvore de chamada profundamente aninhada, o uso repetido desse padrão (anti -?) Leva ao uso exagerado da pilha. (Imagine uma árvore de chamadas com 20 níveis de profundidade, onde, em cada nível, por diferentes razões, a função superaloca cegamente um buffer de 1024 bytes "apenas por segurança", quando geralmente usa apenas 16 ou menos deles, e apenas em casos raros podem usar mais.) Uma alternativa é usar
alloca()
ou VLAs e aloque apenas o espaço de pilha necessário para sua função, para evitar sobrecarregar desnecessariamente a pilha. Felizmente, quando uma função na árvore de chamadas precisa de uma alocação maior que o normal, outras ainda estão usando suas alocações pequenas normais e o uso geral da pilha de aplicativos é significativamente menor do que se todas as funções superalocassem cegamente um buffer local .Mas se você optar por usar
alloca()
...Com base em outras respostas nesta página, parece que os VLAs devem ser seguros (eles não compõem alocações de pilha se chamados de dentro de um loop), mas se você estiver usando
alloca()
, tenha cuidado para não usá-lo dentro de um loop e faça verifique se sua função não pode ser incorporada se houver alguma chance de ser chamada no loop de outra função.fonte
alloca()
é verdade, mas pode-se dizer o mesmo dos vazamentos de memóriamalloc()
(por que não usar um GC então? Alguém poderia argumentar).alloca()
quando usado com cuidado pode ser realmente útil para diminuir o tamanho da pilha.Todo mundo já apontou a grande coisa que é o comportamento indefinido potencial de um estouro de pilha, mas devo mencionar que o ambiente Windows possui um ótimo mecanismo para capturar isso usando exceções estruturadas (SEH) e páginas de proteção. Como a pilha cresce apenas conforme necessário, essas páginas de proteção residem em áreas não alocadas. Se você alocá-los (excedendo a pilha), uma exceção será lançada.
Você pode capturar essa exceção SEH e chamar _resetstkoflw para redefinir a pilha e continuar no seu caminho alegre. Não é o ideal, mas é outro mecanismo para pelo menos saber que algo deu errado quando o material atinge o ventilador. * Nix pode ter algo semelhante que eu não conheço.
Eu recomendo limitar seu tamanho máximo de alocação, envolvendo alloca e rastreando-o internamente. Se você fosse realmente sincero, jogaria algumas sentinelas de escopo na parte superior da sua função para rastrear alocações de aloca no escopo e na sanidade da função e verifique isso com o valor máximo permitido para o seu projeto.
Além disso, além de não permitir vazamentos de memória, o alloca não causa fragmentação de memória, o que é muito importante. Não acho que alloca seja uma má prática se você a usar de maneira inteligente, o que é basicamente verdadeiro para tudo. :-)
fonte
alloca()
pode exigir tanto espaço que o stackpointer cai no monte. Com isso, um invasor que pode controlar o tamanhoalloca()
e os dados que entram nesse buffer podem substituir o heap (o que é muito ruim).alloca () é agradável e eficiente ... mas também está profundamente quebrado.
Na maioria dos casos, você pode substituí-lo usando variáveis locais e tamanho majorante. Se for usado para objetos grandes, colocá-los na pilha geralmente é uma idéia mais segura.
Se você realmente precisa do C, pode usar o VLA (sem vla em C ++, muito ruim). Eles são muito melhores que alloca () em relação ao comportamento e consistência do escopo. A meu ver, o VLA é uma espécie de alloca () corrigida .
É claro que uma estrutura ou matriz local usando um majorante do espaço necessário ainda é melhor, e se você não tiver essa alocação de heap majorante usando malloc () simples, provavelmente é sensato. Não vejo nenhum caso de uso sensato em que você realmente precise de alloca () ou VLA.
fonte
alloca
não cria um nome, apenas um intervalo de memória que tem vida útil .alloca
oumalloc
oufree
diretamente. Eu digo coisas como{stack|heap}_alloc_{bytes,items,struct,varstruct}
e{stack|heap}_dealloc
. Então,heap_dealloc
apenas chamafree
estack_dealloc
é um não-op. Dessa forma, as alocações de pilha podem ser facilmente rebaixadas para alocações de heap, e as intenções também são mais claras.Aqui está o porquê:
Não que alguém escreva esse código, mas o argumento de tamanho para o qual você está passando
alloca
quase certamente vem de algum tipo de entrada, que poderia ter como objetivo malicioso levar seu programa aalloca
algo enorme como esse. Afinal, se o tamanho não é baseado na entrada ou não tem a possibilidade de ser grande, por que você simplesmente não declarou um buffer local pequeno e de tamanho fixo?Praticamente todo o código que usa
alloca
e / ou o C99 vlas possui bugs sérios que levarão a falhas (se você tiver sorte) ou comprometimento de privilégios (se você não tiver tanta sorte).fonte
alloca
. Você disse que quase todo código que o utiliza tem um bug, mas eu estava pensando em usá-lo; eu normalmente ignoraria essa afirmação, mas chegaria Estou escrevendo uma máquina virtual e gostaria de alocar variáveis que não escapam da função na pilha, em vez de dinamicamente, devido à enorme aceleração. Existe uma alternativa ? abordagem que tem as mesmas características de desempenho Eu sei que posso chegar perto com pools de memória, mas que ainda não é tão barato que você faria.?*0 = 9;
INCRÍVEL !!! Eu acho que nunca devo usar ponteiros (ou pelo menos desreferenciá-los). Err, espera. Eu posso testar para ver se é nulo. Hmm. Acho que também posso testar o tamanho da memória que quero alocar viaalloca
. Homem esquisito. Esquisito.*0=9;
não é válido C. Quanto a testar o tamanho para o qual você passaalloca
, teste contra o quê? Não há como saber o limite e, se você for testá-lo em um pequeno tamanho seguro conhecido (por exemplo, 8k), use uma matriz de tamanho fixo na pilha.small_constant * log(user_input)
, provavelmente teremos memória suficiente.Não acho que alguém tenha mencionado isso: o uso de alloca em uma função dificultará ou desabilitará algumas otimizações que poderiam ser aplicadas na função, pois o compilador não pode saber o tamanho do quadro de pilha da função.
Por exemplo, uma otimização comum dos compiladores C é eliminar o uso do ponteiro de quadro dentro de uma função; acessos ao quadro são feitos em relação ao ponteiro da pilha; então há mais um registro para uso geral. Mas se alloca for chamado dentro da função, a diferença entre sp e fp será desconhecida para parte da função, portanto, essa otimização não pode ser feita.
Dada a raridade de seu uso e seu status obscuro como uma função padrão, os projetistas de compiladores possivelmente desativam qualquer otimização que possa causar problemas com o alloca, se for necessário mais do que um pequeno esforço para fazê-lo funcionar com o alloca.
ATUALIZAÇÃO: Como matrizes locais de tamanho variável foram adicionadas a C e, como apresentam aloca problemas de geração de código muito semelhantes aos do alloca, vejo que 'raridade de uso e status obscuro' não se aplica ao mecanismo subjacente; mas eu ainda suspeitaria que o uso de alloca ou VLA tende a comprometer a geração de código dentro de uma função que os use. Gostaria de receber qualquer feedback dos designers do compilador.
fonte
Uma armadilha
alloca
é que alongjmp
rebobina.Ou seja, se você salvar um contexto com
setjmp
, em seguida,alloca
um pouco de memória, em seguida,longjmp
para o contexto, você pode perder aalloca
memória. O ponteiro da pilha está de volta onde estava e, portanto, a memória não é mais reservada; se você chamar uma função ou executar outraalloca
, você derrotará o originalalloca
.Para esclarecer, o que estou me referindo especificamente aqui é uma situação em
longjmp
que não retorna da função em quealloca
ocorreu! Em vez disso, uma função salva o contexto comsetjmp
; então aloca memória comalloca
e, finalmente, um longjmp ocorre nesse contexto. Aalloca
memória dessa função não é toda liberada; apenas toda a memória que alocou desde osetjmp
. Claro, estou falando de um comportamento observado; nenhum requisito desse tipo está documentado sobre algumalloca
que eu conheça.O foco na documentação geralmente está no conceito de que a
alloca
memória está associada a uma ativação de função , não a qualquer bloco; que várias invocaçõesalloca
simplesmente capturam mais memória da pilha, que é liberada quando a função termina. Não tão; a memória está realmente associada ao contexto do procedimento. Quando o contexto é restaurado comlongjmp
, o mesmo ocorre com oalloca
estado anterior . É uma conseqüência do próprio registro de ponteiro de pilha ser usado para alocação e também (necessariamente) salvo e restaurado no arquivojmp_buf
.Aliás, isso, se funcionar dessa maneira, fornece um mecanismo plausível para deliberadamente liberar memória que foi alocada com
alloca
.Eu corri para isso como a causa raiz de um bug.
fonte
longjmp
retorna e faz com que o programa esqueça tudo o que aconteceu na pilha: todas as variáveis, chamadas de função etc. Ealloca
é como uma matriz na pilha, portanto, espera-se que sejam derrotadas como tudo na pilha.man alloca
deu a seguinte frase: "Como o espaço alocado por alloca () é alocado no quadro da pilha, esse espaço é liberado automaticamente se o retorno da função for saltado por uma chamada para longjmp (3) ou siglongjmp (3).". Portanto, está documentado que a memória alocada comalloca
é derrotada após alongjmp
.longjmp
. A função de destino ainda não retornou. Já fezsetjmp
,alloca
e entãolongjmp
. Olongjmp
pode rebobinar oalloca
estado de volta ao que era naquelesetjmp
tempo. Ou seja, o ponteiro movido poralloca
sofre do mesmo problema que uma variável local que não foi marcadavolatile
!setjmp
entãoalloca
, e entãolongjmp
, é normal quealloca
fosse rebobinado. O objetivo de tudolongjmp
é voltar ao estado em que foi salvosetjmp
!Um local onde
alloca()
é especialmente perigoso do quemalloc()
o kernel - o kernel de um sistema operacional típico possui um espaço de pilha de tamanho fixo codificado em um de seus cabeçalhos; não é tão flexível quanto a pilha de um aplicativo. Fazer uma chamada paraalloca()
um tamanho não autorizado pode causar uma falha no kernel. Certos compiladores avisam o usoalloca()
(e até mesmo de VLAs) sob certas opções que devem ser ativadas durante a compilação de um código do kernel - aqui, é melhor alocar memória no heap que não é corrigido por um limite codificado.fonte
alloca()
não é mais perigoso do queint foo[bar];
ondebar
está um número inteiro arbitrário.Se você acidentalmente gravar além do bloco alocado com
alloca
(devido a um estouro de buffer, por exemplo), substituirá o endereço de retorno da sua função, porque esse está localizado "acima" na pilha, ou seja, após o bloco alocado.A consequência disso é dupla:
O programa falhará espetacularmente e será impossível dizer por que ou onde ele falhou (a pilha provavelmente se descontrairá em um endereço aleatório devido ao ponteiro do quadro substituído).
Isso torna o buffer overflow muitas vezes mais perigoso, pois um usuário mal-intencionado pode criar uma carga útil especial que seria colocada na pilha e, portanto, acabaria sendo executada.
Por outro lado, se você escrever além de um bloco na pilha, "apenas" terá corrupção na pilha. O programa provavelmente será encerrado inesperadamente, mas irá desenrolar a pilha corretamente, reduzindo assim a chance de execução de código malicioso.
fonte
alloca
.alloca
em comparação commalloc
(portanto, não um buffer de tamanho fixo na pilha).Infelizmente, o verdadeiramente impressionante
alloca()
está faltando no tcc quase incrível. Gcc temalloca()
.Semeia a semente de sua própria destruição. Com retorno como destruidor.
Como se
malloc()
ele retornasse um ponteiro inválido em caso de falha, que irá falhar nos sistemas modernos com uma MMU (e esperamos reiniciar aqueles sem).Diferente das variáveis automáticas, você pode especificar o tamanho no tempo de execução.
Funciona bem com recursão. Você pode usar variáveis estáticas para obter algo semelhante à recursão de cauda e usar apenas algumas outras informações de passagem para cada iteração.
Se você for muito fundo, terá a garantia de um segfault (se você tiver uma MMU).
Observe que ele
malloc()
não oferece mais, pois retorna NULL (que também será segfault se atribuído) quando o sistema estiver sem memória. Ou seja, tudo o que você pode fazer é pagar a fiança ou apenas tentar atribuí-lo de qualquer maneira.Para usar
malloc()
, uso globals e atribuo a eles NULL. Se o ponteiro não for NULL, libero-o antes de usá-lomalloc()
.Você também pode usar
realloc()
como caso geral se desejar copiar dados existentes. Você precisa verificar o ponteiro antes para descobrir se deseja copiar ou concatenar após orealloc()
.3.2.5.2 Vantagens da alloca
fonte
Os processos têm apenas uma quantidade limitada de espaço na pilha disponível - muito menos do que a quantidade de memória disponível
malloc()
.Ao usá-
alloca()
lo, você aumenta drasticamente suas chances de obter um erro de Estouro de pilha (se tiver sorte ou uma falha inexplicável, se não tiver).fonte
Não é muito bonito, mas se o desempenho realmente importa, você pode pré-alocar algum espaço na pilha.
Se você já tem o tamanho máximo da memória bloqueado e precisa manter verificações de excesso, faça algo como:
fonte
A função alloca é ótima e todos os opositores estão simplesmente espalhando FUD.
Matriz e parray são EXATAMENTE iguais, com EXATAMENTE os mesmos riscos. Dizer que um é melhor que o outro é uma escolha sintática, não técnica.
Quanto à escolha de variáveis de pilha versus variáveis de heap, há muitas vantagens em programas de longa execução usando pilha sobre heap para variáveis com vida útil no escopo. Você evita a fragmentação de heap e pode aumentar o espaço do processo com espaço de heap não utilizado (inutilizável). Você não precisa limpá-lo. Você pode controlar a alocação de pilha no processo.
Por que isso é ruim?
fonte
Na verdade, não é garantido que o alloca use a pilha. De fato, a implementação do alloca do gcc-2.95 aloca memória do heap usando o próprio malloc. Além disso, essa implementação é incorreta, pode levar a um vazamento de memória e a um comportamento inesperado se você a chamar dentro de um bloco com um uso adicional de goto. Não, para dizer que você nunca deve usá-lo, mas algumas vezes alloca leva a mais sobrecarga do que libera.
fonte
alloca
. Como ele teria limpado a memória quandolongjmp
é usado para abandonar os quadros que funcionavamalloca
? Quando alguém usaria o gcc 2.95 hoje?IMHO, alloca é considerado uma má prática, porque todo mundo tem medo de esgotar o limite de tamanho da pilha.
Eu aprendi muito lendo este tópico e alguns outros links:
Eu uso o alloca principalmente para tornar meus arquivos C simples compiláveis no msvc e gcc sem nenhuma alteração, estilo C89, sem #ifdef _MSC_VER, etc.
Obrigado ! Este tópico me fez inscrever neste site :)
fonte
Na minha opinião, alloca (), quando disponível, deve ser usado apenas de maneira restrita. Muito parecido com o uso de "goto", um grande número de pessoas razoáveis tem forte aversão não apenas ao uso de, mas também à existência de alloca ().
Para uso incorporado, onde o tamanho da pilha é conhecido e os limites podem ser impostos por convenção e análise sobre o tamanho da alocação e onde o compilador não pode ser atualizado para oferecer suporte ao C99 +, o uso de alloca () é bom, e eu estive conhecido por usá-lo.
Quando disponíveis, os VLAs podem ter algumas vantagens sobre alloca (): O compilador pode gerar verificações de limite de pilha que obterão acesso fora dos limites quando o acesso ao estilo de matriz for usado (não sei se algum compilador faz isso, mas pode ser feita) e a análise do código pode determinar se as expressões de acesso à matriz estão adequadamente delimitadas. Observe que, em alguns ambientes de programação, como automotivo, equipamentos médicos e aviônicos, essa análise deve ser feita mesmo para matrizes de tamanho fixo, tanto automáticas (na pilha) quanto alocação estática (global ou local).
Em arquiteturas que armazenam dados e retornam endereços / ponteiros de quadro na pilha (pelo que sei, são todos eles), qualquer variável alocada à pilha pode ser perigosa porque o endereço da variável pode ser obtido e valores de entrada não verificados podem permitir todos os tipos de travessuras.
A portabilidade é menos preocupante no espaço incorporado, no entanto, é um bom argumento contra o uso de alloca () fora de circunstâncias cuidadosamente controladas.
Fora do espaço incorporado, usei alloca () principalmente dentro das funções de registro e formatação para obter eficiência, e em um scanner lexical não recursivo, em que estruturas temporárias (alocadas usando alloca () são criadas durante a tokenização e a classificação e, em seguida, um persistente O objeto (alocado via malloc ()) é preenchido antes do retorno da função.O uso de alloca () para estruturas temporárias menores reduz bastante a fragmentação quando o objeto persistente é alocado.
fonte
A maioria das respostas aqui em grande parte esquece o ponto: há uma razão pela qual o uso
_alloca()
é potencialmente pior do que simplesmente armazenar objetos grandes na pilha.A principal diferença entre o armazenamento automático e
_alloca()
o fato de este sofrer um problema adicional (sério): o bloco alocado não é controlado pelo compilador ; portanto, não há como otimizar ou reciclar o compilador.Comparar:
com:
O problema com o último deve ser óbvio.
fonte
alloca
(sim, digo VLA, porquealloca
é mais do que apenas criador de matrizes de tamanho estatístico)?Eu não acho que alguém tenha mencionado isso, mas a alloca também tem alguns problemas sérios de segurança que não estão necessariamente presentes no malloc (embora esses problemas também surjam com qualquer matriz baseada em pilha, dinâmica ou não). Como a memória está alocada na pilha, os estouros / estouros de buffer têm consequências muito mais sérias do que apenas com malloc.
Em particular, o endereço de retorno para uma função é armazenado na pilha. Se esse valor for corrompido, seu código poderá ser criado para ir para qualquer região executável da memória. Os compiladores fazem um grande esforço para dificultar isso (em particular ao aleatorizar o layout do endereço). No entanto, isso é claramente pior do que apenas um estouro de pilha, pois o melhor caso é um SEGFAULT se o valor de retorno estiver corrompido, mas também pode começar a executar uma parte aleatória da memória ou, no pior caso, alguma região da memória que comprometa a segurança do programa. .
fonte