Pergunta

alloca() aloca memória na pilha, ao invés de incluir na pilha, como no caso de malloc().Então, quando eu voltar da rotina que a memória é liberada.Então, na verdade, isso resolve o meu problema de liberar a memória alocada dinamicamente.A liberação de memória alocada por meio de malloc() é uma grande dor de cabeça e se de alguma forma perdeu leva a todos os tipos de problemas de memória.

Porque é que o uso de alloca() desanimado, apesar das características acima?

Foi útil?

Solução

A resposta é bem ali na página man (pelo menos no Linux ):

valor de retorno A função alloca () retorna um apontador para o início do espaço alocado. Se o causas de alocação estouro de pilha, o comportamento do programa é indefinida.

O que não quer dizer que nunca deve ser usado. Um dos projetos de OSS eu trabalho utiliza extensivamente, e contanto que você não está abusar dela (alloca'ing valores enormes), está tudo bem. Uma vez que você passar a marca "algumas centenas de bytes", vez é para uso malloc e amigos, em vez disso. Você ainda pode obter falhas de alocação, mas pelo menos você vai ter alguma indicação do fracasso em vez de apenas soprar a pilha.

Outras dicas

Um dos mais erros memoráveis ??que tive foi a ver com uma função incorporada que alloca usado. Ele se manifestou como um estouro de pilha (porque ele aloca na pilha) em pontos aleatórios de execução do programa.

No arquivo de cabeçalho:

void DoSomething() {
   wchar_t* pStr = alloca(100);
   //......
}

No arquivo de implementação:

void Process() {
   for (i = 0; i < 1000000; i++) {
     DoSomething();
   }
}

Então, o que aconteceu foi a função DoSomething compilador embutido e todas as alocações de pilha estavam acontecendo função dentro Process() e soprando assim a pilha para cima. Em minha defesa (e eu não era o único que encontrei o problema, eu tinha que ir e grito de um dos desenvolvedores seniores, quando eu não poderia consertá-lo), não foi alloca reta, que foi uma das cordas ATL macros de conversão.

Assim, a lição é -. Não uso alloca em funções que você acha que pode ser embutido

velha questão, mas ninguém mencionou que ele deve ser substituído por matrizes de comprimento variável.

char arr[size];

em vez de

char *arr=alloca(size);

É no C99 padrão e existia como extensão do compilador em muitos compiladores.

alloca() é muito útil se você não pode usar um padrão variável de local por causa de seu tamanho teria que ser determinada em tempo de execução e pode absolutamente garantia de que o ponteiro que você começa a partir alloca() NUNCA vai ser usado depois que esta função retorna.

Você pode ser bastante seguro, se você

  • não devolver o ponteiro, ou qualquer coisa que o contém.
  • não armazenar o ponteiro em qualquer estrutura, alocado no heap
  • não deixe que qualquer outro segmento use o ponteiro

O perigo real vem a chance de que alguém irá violar estas condições, algum tempo depois.Com isso em mente, é ótimo para passar buffers para as funções que o formato de texto para eles :)

Como observado no este newsgroup , existem algumas razões por que usar alloca pode ser considerado difícil e perigoso:

  • Não todo o apoio compiladores alloca.
  • Alguns compiladores interpretar o comportamento pretendido do alloca diferente, por isso a portabilidade não é garantida mesmo entre compiladores que o suportam.
  • Algumas implementações são buggy.

Uma questão é que não é padrão, embora seja amplamente apoiada. Outras coisas sendo iguais, eu sempre usar uma função padrão em vez de uma extensão de compilador comum.

Ainda alloca uso é desaconselhado, por quê?

Eu não percebem tal consenso. Muita pros fortes; alguns contras:

  • C99 proporciona matrizes de comprimento variável, o que muitas vezes ser utilizados preferencialmente como o da notação mais consistente com matrizes de comprimento fixo e intuitiva geral
  • muitos sistemas tem memória / espaço de endereço menos global disponível para a pilha do que eles fazem para o heap, o que torna o programa um pouco mais suscetíveis à exaustão de memória (através de estouro de pilha): isto pode ser visto como um bom ou um mau coisa - uma das razões da pilha não cresce automaticamente o modo pilha faz é impedir out-of-control programas de ter tanto impacto adverso sobre toda a máquina
  • quando utilizado em um âmbito mais local (tal como um circuito while ou for) ou em diversos âmbitos, a memória acumula por iteração / âmbito e não é libertado até as saídas de função: Isto contrasta com variáveis ??normais definidas no âmbito de uma estrutura de controle (por exemplo for {int i = 0; i < 2; ++i) { X } iria acumular memória alloca-ed solicitado em X, mas a memória para uma matriz de tamanho fixo seria reciclado por iteração).
  • compiladores modernos normalmente não funciona inline essa chamada alloca, mas se você forçá-los em seguida, o alloca vai acontecer no contexto dos chamadores (ou seja, a pilha não será lançado até o chamador retornos)
  • há muito tempo alloca a transição de um recurso não-portáteis / hack para uma extensão padronizada, mas alguns percepção negativa pode persistir
  • o tempo de vida está vinculado ao escopo da função, que pode ou não pode atender o programador melhor do que o controle explícito de malloc
  • ter que usar malloc encoraja o pensamento sobre o deallocation - se que é gerido através de uma função de invólucro (por exemplo WonderfulObject_DestructorFree(ptr)), então a função fornece um ponto para as operações de implementação limpo para cima (como fechar descritores de arquivos, liberando ponteiros internos ou fazendo algum logging) sem mudanças explícitas para o código do cliente: às vezes é um bom modelo para adotar consistentemente
    • neste estilo pseudo-OO da programação, é natural querer algo como WonderfulObject* p = WonderfulObject_AllocConstructor(); - isso é possível quando o "construtor" é uma função que retorna memória malloc-ed (como os restos de memória alocados após a função retorna o valor a ser armazenado em p), mas não se o "construtor" usa alloca
      • uma versão macro do WonderfulObject_AllocConstructor poderia conseguir isso, mas "macros são maus", em que eles podem entrar em conflito com cada código diferente e não-macro e criar substituições indesejadas e consequentes problemas difíceis de diagnosticar
    • operações free faltando pode ser detectado pelo Valgrind, Purify etc., mas faltam as chamadas "destruidor" nem sempre pode ser detectado em tudo - um benefício muito tênue em termos de execução de uso pretendido; algumas implementações alloca() (tais como GCC de) utilizar uma macro inline para alloca(), então a substituição de tempo de execução de uma biblioteca de diagnóstico de memória-uso não é possível a forma como ele é para malloc / realloc / free (cerca exemplo elétrica)
  • algumas implementações têm problemas sutis: por exemplo, a partir da página de manual Linux:

    Em muitos sistemas alloca () não pode ser usado dentro da lista de argumentos de uma chamada de função, porque o espaço de pilha reservado pelo alloca () iria aparecer na pilha no meio do espaço para os argumentos da função.


Eu sei que esta questão é marcado C, mas como um C ++ programador eu pensei em usar C ++ para ilustrar a utilidade potencial de alloca: o código abaixo (e aqui no ideone ) cria um tracki vectorng tipos polimórficas diferentes tamanhos que são atribuídos pilha (com tempo de vida ligada à função de retorno), em vez de pilha alocada.

#include <alloca.h>
#include <iostream>
#include <vector>

struct Base
{
    virtual ~Base() { }
    virtual int to_int() const = 0;
};

struct Integer : Base
{
    Integer(int n) : n_(n) { }
    int to_int() const { return n_; }
    int n_;
};

struct Double : Base
{
    Double(double n) : n_(n) { }
    int to_int() const { return -n_; }
    double n_;
};

inline Base* factory(double d) __attribute__((always_inline));

inline Base* factory(double d)
{
    if ((double)(int)d != d)
        return new (alloca(sizeof(Double))) Double(d);
    else
        return new (alloca(sizeof(Integer))) Integer(d);
}

int main()
{
    std::vector<Base*> numbers;
    numbers.push_back(factory(29.3));
    numbers.push_back(factory(29));
    numbers.push_back(factory(7.1));
    numbers.push_back(factory(2));
    numbers.push_back(factory(231.0));
    for (std::vector<Base*>::const_iterator i = numbers.begin();
         i != numbers.end(); ++i)
    {
        std::cout << *i << ' ' << (*i)->to_int() << '\n';
        (*i)->~Base();   // optionally / else Undefined Behaviour iff the
                         // program depends on side effects of destructor
    }
}

Todas as outras respostas estão corretas. No entanto, se a coisa que você quer alloc usando alloca() é razoavelmente pequeno, eu acho que é uma boa técnica que é mais rápido e mais conveniente do que usar malloc() ou de outra forma.

Em outras palavras, alloca( 0x00ffffff ) é perigosa e susceptível de causar estouro, exatamente tanto quanto char hugeArray[ 0x00ffffff ]; é. Seja cauteloso e razoável e você vai ficar bem.

Todo mundo já assinalou a grande coisa que é um comportamento indefinido potencial de um estouro de pilha, mas devo mencionar que o ambiente Windows tem um grande mecanismo para pegar isso usando exceções estruturados (SEH) e páginas de proteção. Desde a pilha só cresce conforme necessário, essas páginas de proteção residem em áreas que são não alocado. Se você alocar para eles (pelo transbordamento da pilha) uma exceção é lançada.

Você pode pegar essa exceção SEH e chamar _resetstkoflw para redefinir a pilha e continuar em sua maneira alegre. A sua não é ideal, mas é outro mecanismo para pelo menos saber alguma coisa tem de errado foi quando o material atinge o ventilador. * Nix pode ter algo semelhante que eu não estou ciente de.

Eu recomendo tampando seu tamanho de alocação máximo envolvendo alloca e segui-lo internamente. Se você fosse realmente incondicional sobre isso você pode jogar alguns sentinelas escopo no topo da sua função para rastrear qualquer destinação alloca no âmbito da função e sanidade verificar isso contra o montante máximo permitido para o seu projeto.

Além disso, além de não permitindo vazamentos de memória alloca não causar fragmentação da memória que é muito importante. Eu não acho que alloca é uma prática ruim se você usá-lo de forma inteligente, que é basicamente verdade para tudo. : -)

alloca () é agradável e eficiente ... mas também está profundamente quebrado.

  • comportamento âmbito quebrado (escopo da função em vez do escopo de bloco)
  • uso inconsistant com malloc ( alloca () ponteiro -ted não devem ser libertados, de agora em diante você tem que rastrear onde ponteiros estão vindo para free () única aqueles que você tem com malloc () )
  • mau comportamento quando você também usar inlining (escopo às vezes vai para a função de chamada, dependendo se callee é inlined ou não).
  • nenhuma pilha de verificação de fronteira
  • comportamento indefinido em caso de falha (não retorna NULL como malloc ... e o que significa o insucesso como ele não verifica limites pilha de qualquer maneira ...)
  • Não ansi padrão

Na maioria dos casos, você pode substituí-lo utilizando variáveis ??locais e tamanho majorant. Se ele é usado para grandes objetos, colocando-os na pilha é geralmente uma idéia mais segura.

Se você realmente precisa dele C você pode usar VLA (sem vla em C ++, muito ruim). Eles são muito melhor do que alloca () em relação ao comportamento abrangência e consistência. A meu ver VLA são uma espécie de alloca () fez certo.

É claro que uma estrutura local ou matriz usando um majorant do espaço necessário é ainda melhor, e se você não tem tal alocação de pilha majorant usando malloc simples () é provavelmente sã. Não vejo nenhum caso de uso sã onde você realmente precisa ou alloca () ou VLA.

Muitas respostas interessantes a esta pergunta "velho", até mesmo algumas relativamente novas respostas, mas eu não encontrar algum que mencionar isto ....

Quando usado corretamente e com cuidado, o uso consistente de alloca() (Talvez aplicação à escala) para lidar com pequenas alocações de comprimento variável (Ou C99 VLAs, quando disponível) pode levar a diminuir pilha geral crescimento do que uma implementação de outra forma equivalente usando grandes dimensões matrizes locais de comprimento fixo. Então alloca() pode ser bom para sua pilha se você usá-lo com cuidado.

Eu encontrei essa citação em .... OK, eu fiz essa citação acima. Mas, realmente, pensar nisso ....

@j_random_hacker é muito bem aos seus comentários sob outras respostas: Evitar o uso de alloca() em favor de matrizes locais de grandes dimensões não tornar o seu programa mais seguro contra estouros de pilha (a menos que seu compilador é suficiente idade para permitir inlining de funções que usam alloca() caso em que você deve atualizar ou menos que você use alloca() dentro de loops, caso em que você deve ... não usar alloca() dentro de loops).

Eu trabalhei em ambientes de desktop / servidor e sistemas embarcados. Um monte de sistemas embarcados não use uma pilha em tudo (nem sequer ligar no suporte para ele), por razões que incluem a percepção de que a memória alocada dinamicamente é mal devido aos riscos de vazamentos de memória em um aplicativo que não nunca reinicia por anos em um tempo, ou a justificativa mais razoável que a memória dinâmica é perigoso porque não pode ser conhecido com certeza que um aplicativo nunca vai fragmentar seu acervo para o ponto de exaustão de memória falsa. programadores tão incorporados ficam com poucas alternativas.

alloca() (ou Vlas) pode ser apenas a ferramenta certa para o trabalho.

Eu vi o tempo e outra vez em que um programador faz um buffer "grande o suficiente para lidar com qualquer caso possível" atribuída-stack. Em uma árvore chamada profundamente aninhada, o uso repetido de que (anti -?) Padrão leva a utilização pilha exagerada. (Imagine uma árvore de chamadas 20 níveis de profundidade, onde em cada nível, por diferentes razões, a função cegamente over-aloca um buffer de 1024 bytes "apenas para ser seguro", quando geralmente ele só vai usar 16 ou menos deles, e apenas em muito casos raros, pode usar mais.) Uma alternativa é usar alloca() ou VLAs e alocar apenas como espaço de pilha tanto quanto suas necessidades de função, para evitar encargos desnecessários aos pilha. Espero que, quando uma função na árvore de chamada precisa de uma alocação maior que a normal, outros na árvore chamada ainda estão usando seus pequenos atribuições normais, eo uso geral da pilha de aplicativos é significativamente menor do que se cada função cegamente sobre-atribuído um buffer local .

Mas se você optar por usar alloca() ...

Com base em outras respostas nesta página, parece que VLAs deve ser seguro (eles fazem alocações de pilha não compostos, se chamado a partir de um loop), mas se você estiver usando alloca(), tome cuidado para não usá-lo dentro de um loop, e make certeza a sua função não pode ser embutido se há alguma chance de que poderia ser chamado de dentro alça de outra função.

Aqui está o porquê:

char x;
char *y=malloc(1);
char *z=alloca(&x-y);
*z = 1;

Não que alguém iria escrever este código, mas o argumento tamanho que você está passando para alloca quase certamente vem de algum tipo de entrada, o que poderia maliciosamente visam obter o seu programa para alloca algo grande assim. Afinal, se o tamanho não é baseada na entrada ou não tem a possibilidade de ser grande, por que não simplesmente declarar, um buffer local de tamanho fixo pequena?

Praticamente todo o código usando alloca e / ou Vlas C99 tem erros graves, que vai levar a falhas (se tiver sorte) ou compromisso privilégio (se você não tem tanta sorte).

Um lugar onde alloca() é especialmente perigoso do que malloc() é o núcleo - núcleo de um sistema operacional típico tem um espaço de pilha tamanho fixo codificado em um dos seu cabeçalho; não é tão flexível como a pilha de uma aplicação. Fazer uma chamada para alloca() com um tamanho injustificado pode causar o kernel para falhar. Alguns compiladores avisar uso de alloca() (e até mesmo VLAs para que o assunto), sob certas opções que deve ser ligado ao compilar um código do kernel - aqui, é melhor alocar memória no heap que não é fixo por um limite hard-coded .

Se você acidentalmente escrever para além do bloco alocado com alloca (devido a um estouro de buffer, por exemplo), então você vai substituir o endereço de retorno de sua função, porque isso é uma localizado "acima" na a pilha, ou seja, após seu bloco alocado.

_ alloca bloco na pilha

A consequência disto é duas vezes:

  1. O programa irá falhar espetacularmente e será impossível dizer por que ou onde ele caiu (pilha provavelmente irá desenrolar a um endereço aleatório devido ao ponteiro do quadro sobrescrito).

  2. Faz buffer overflow muitas vezes mais perigoso, uma vez que um utilizador mal intencionado pode criar uma carga especial que seria colocado na pilha e, portanto, pode acabar executado.

Por outro lado, se você escrever para além de um bloco na pilha você "apenas" get corrupção de pilha. O programa provavelmente irá terminar inesperadamente, mas vai desenrolar a pilha corretamente, reduzindo assim a possibilidade de execução de código malicioso.

Uma armadilha com alloca é que longjmp rebobina-lo.

Ou seja, se você salvar um contexto com setjmp, então alloca alguma memória, então longjmp com o contexto, você pode perder a memória alloca (sem qualquer tipo de aviso prévio). O ponteiro da pilha está de volta onde estava e assim a memória não é mais reservada; se você chamar uma função ou fazer outra alloca, você vai espancar a alloca originais.

Para esclarecer, o que estou referindo-se especificamente aqui é uma situação em que longjmp não retornar para fora da função onde o alloca ocorreu! Em vez disso, uma função de salva contexto com setjmp; em seguida, aloca memória com alloca e, finalmente, um longjmp ocorre a esse contexto. memória alloca dessa função não é tudo liberado; apenas toda a memória que ele alocados desde o setjmp. Claro, estou falando de um comportamento observado; essa exigência não está documentado de qualquer alloca que eu sei.

O foco na documentação é geralmente no conceito de que a memória alloca está associada com uma função ativação, não com qualquer bloco; que várias chamadas de alloca basta pegar mais memória de pilha que tudo é liberado quando o termina função. Não tão; a memória é realmente associado com o contexto procedimento. Quando o contexto é restaurado com longjmp, então é o estado alloca antes. É uma consequência do ponteiro de pilha se registrar sendo usado para alocação, e também (necessariamente) salvos e restaurados na jmp_buf.

Aliás, este, se ele funciona dessa forma, fornece um mecanismo plausível para libertar deliberadamente memória que foi alocada com alloca.

Eu tenho que correr para isso como a causa de um bug.

Eu não acho que ninguém tenha mencionado o seguinte: Uso de alloca em uma função irá dificultar ou desativar algumas otimizações que poderiam ser aplicados na função, uma vez que o compilador não pode saber o tamanho do quadro de pilha da função.

Por exemplo, uma optimização comum por compiladores C é o de eliminar o uso do ponteiro dentro de uma função, acessos frame são feitos em relação ao ponteiro de pilha em vez; então não há mais um registro para uso geral. Mas se alloca é chamado dentro da função, a diferença entre sp e fp será desconhecido por parte da função, então essa otimização não pode ser feito.

Dada a raridade de seu uso, e seu status obscuro como uma função padrão, os designers do compilador possivelmente desativar qualquer otimização que pode causa problemas com alloca, se tomaria mais do que um pouco de esforço para torná-lo trabalhar com alloca.

UPDATE: Desde de comprimento variável matrizes locais foram adicionados ao C e C ++, e uma vez que estes apresentam problemas muito semelhantes de geração de código para o compilador como alloca, vejo que 'raridade de utilização e status obscuro' não se aplica ao mecanismo subjacente; mas eu ainda iria suspeitar que o uso de qualquer alloca ou VLA tende a geração de código compromisso dentro de uma função que usa-los. Eu gostaria de receber qualquer feedback dos desenhadores do compilador.

Infelizmente o alloca() verdadeiramente incrível está faltando a partir do tcc quase incrível. Gcc tem alloca().

  1. Ele semeia a semente de sua própria destruição. Com o retorno como o destruidor.

  2. Como malloc() ele retorna um ponteiro inválido em deixar que segfault em sistemas modernos com uma MMU (e esperemos que reiniciar aqueles sem).

  3. variáveis ??auto Ao contrário você pode especificar o tamanho em tempo de execução.

Ele funciona bem com recursividade. Você pode usar variáveis ??estáticas para alcançar algo semelhante a recursão de cauda e usar apenas alguns outros passam informações para cada iteração.

Se você empurrar demasiado profundo você tem a certeza de um segfault (se você tem uma MMU).

Note que ofertas malloc() não mais como ele retorna NULL (que também irá segfault se atribuído) quando o sistema está sem memória. Ou seja, tudo o que você pode fazer é fiança ou apenas tentar atribuí-lo qualquer forma.

Para usar malloc() eu uso globals e atribuí-los NULL. Se o ponteiro não é NULL eu libertá-lo antes de eu usar malloc().

Você também pode usar realloc() como caso geral se copiar falta quaisquer dados existentes. Você precisa verificar ponteiro antes de trabalhar para fora se você estiver indo para copiar ou concatenar após a realloc().

3.2.5.2 Vantagens de alloca

Processos só tem uma quantidade limitada de espaço de pilha disponível -. Muito menos do que a quantidade de memória disponível para malloc()

Ao usar alloca() você aumentar drasticamente suas chances de obter um erro de estouro de pilha (se você tiver sorte, ou um acidente inexplicável, se você não é).

Não é muito bonito, mas se o desempenho realmente importa, você pode pré-alocar algum espaço na pilha.

Se você já agora o tamanho máximo da memória bloquear sua necessidade e você quer manter estouro cheques, você poderia fazer algo como:

void f()
{
    char array_on_stack[ MAX_BYTES_TO_ALLOCATE ];
    SomeType *p = (SomeType *)array;

    (...)
}

Na verdade, alloca não são garantidos para utilizar a pilha. Na verdade, o gcc-2.95 implementação de alloca Aloca memória da pilha usando o próprio malloc. Igualmente que a implementação é buggy, pode levar a um vazamento de memória e algum comportamento inesperado se você chamá-lo dentro de um bloco com uma maior utilização de Goto. Não, quer dizer que você nunca deve usá-lo, mas algumas vezes alloca leva a mais sobrecarga do que releaves Frome.

A função alloca é grande e e todos os opositores são simplesmente espalhar FUD.

void foo()
{
    int x = 50000; 
    char array[x];
    char *parray = (char *)alloca(x);
}

Matriz e PArray são exatamente o mesmo com exatamente os mesmos riscos. Dizendo que um é melhor que o outro é uma escolha sintática, não um técnico.

Como para a escolha de variáveis ??de pilha vs variáveis ??de pilha, há uma série de vantagens para programas de longo execução usando pilha sobre o montão para variáveis ??com vidas no escopo. Você evitar a fragmentação heap e você pode evitar o crescimento de seu espaço de processo com não utilizado (inutilizável) espaço de pilha. Você não precisa limpá-lo. Você pode controlar a alocação de pilha sobre o processo.

Por que isso é ruim?

IMHO, alloca é considerado uma má prática porque todo mundo tem medo de esgotar o limite de tamanho da pilha.

Eu aprendi muito lendo esta discussão e alguns outros links:

Eu uso alloca principalmente para fazer minha simples C arquivos compilable em msvc e gcc sem qualquer alteração, o estilo C89, não _MSC_VER #ifdef, etc.

Obrigado! Esta discussão fez-me inscrever para este site:)

Na minha opinião, alloca (), quando disponível, deve ser usado apenas de forma restrita. Muito bem como o uso de "goto", um número bastante grande de pessoas de outra forma razoáveis ??têm forte aversão não apenas para o uso de, mas também a existência de, alloca ().

Para uso incorporado, onde o tamanho da pilha é conhecido e limites pode ser imposta através de convenções e análises sobre o tamanho da alocação, e onde o compilador não pode ser atualizado para suportar C99 +, uso de alloca () é bom, e eu 've sido conhecida a usá-lo.

Quando disponível, VLAs pode ter algumas vantagens sobre alloca (): O compilador pode gerar verificações de limite de pilha que vai pegar o acesso fora dos limites quando o acesso estilo matriz é usada (Eu não sei se algum compiladores fazer isso, mas isso pode ser feito), e análise do código pode determinar se as expressões acesso à matriz são devidamente delimitada. Note-se que, em alguns ambientes de programação, tais como, equipamentos médicos automotivo, e aviônicos, esta análise tem que ser feito mesmo para matrizes de tamanho fixo, tanto automática (na pilha) e estático alocação (global ou local).

Em arquiteturas que armazenam os endereços de dados e de retorno / ponteiros do quadro na pilha (pelo que eu sei, isso é tudo deles), qualquer variável de pilha alocada pode ser perigoso porque o endereço da variável pode ser tomada, ea entrada desmarcada valores pode permitir que todos os tipos de travessuras.

A portabilidade é uma preocupação menor no espaço incorporado, no entanto, é um bom argumento contra o uso de alloca exterior () de circunstâncias cuidadosamente controladas.

Do lado de fora do espaço incorporado, eu usei alloca () logging principalmente dentro e formatação funções de eficiência, e em um scanner lexical não-recursivo, onde as estruturas temporárias (alocados usando alloca () são criados durante tokenization e classificação, em seguida, um objeto persistente (alocado via malloc ()) é preenchido antes de a função retorna. o uso de alloca () para as estruturas temporárias menores reduz grandemente fragmentação quando o objecto persistente é alocado.

A maioria das respostas aqui em grande parte, perder o ponto: há uma razão por que usar _alloca() é potencialmente pior do que simplesmente armazenar grandes objetos na pilha

.

A principal diferença entre o armazenamento automático e _alloca() é que este último sofre de um problema adicional (sério): o bloco alocado é não controlado pelo compilador , então não há nenhuma maneira para que o compilador para otimizar ou reciclar-lo.

Compare:

while (condition) {
    char buffer[0x100]; // Chill.
    /* ... */
}

com:

while (condition) {
    char* buffer = _alloca(0x100); // Bad!
    /* ... */
}

O problema com este último deve ser óbvio.

Eu não acho que ninguém tenha mencionado isso, mas alloca também tem alguns sérios problemas de segurança não necessariamente apresentam com malloc (embora estas questões também surgem com qualquer matrizes baseado em pilha, dinâmico ou não). Como a memória é alocada na pilha, buffer overflows / underflows ter consequências muito mais graves do que com apenas malloc.

Em particular, o endereço de retorno para uma função é armazenado na pilha. Se este valor for corrompido, o código poderia ser feito para ir a qualquer região executável da memória. Compiladores não medem esforços para tornar esta difícil (em particular, randomizando layout de endereço). No entanto, este é claramente pior do que apenas um estouro de pilha desde o melhor caso é um segfault se o valor de retorno está corrompido, mas também pode começar a executar um pedaço aleatório de memória ou no pior caso alguma região da memória que compromete a segurança do seu programa .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top