Pergunta

Existe uma maneira de saber e de saída o tamanho da pilha necessário para uma função em tempo de compilação em C? Aqui está o que eu gostaria de saber:

Vamos dar alguma função:

void foo(int a) {
    char c[5];
    char * s;
    //do something
    return;
}

Ao compilar esta função, gostaria de saber quanto espaço de pilha ele irá consumir whent ele é chamado. Isto pode ser útil para detectar a sobre a declaração da pilha de uma estrutura escondendo um grande buffer.

Eu estou procurando algo que iria imprimir algo como isto:

arquivo foo.c: função de uso da pilha foo é n bytes

Existe uma maneira de não olhar para o gerado montagem de saber isso? Ou um limite que pode ser definido para o compilador?

Update: Eu não estou tentando evitar estouro de pilha de tempo de execução para um determinado processo, eu estou procurando uma maneira de encontrar antes de tempo de execução, se um uso da pilha função, conforme determinado pelo compilador, está disponível como uma saída da compilação processo.

Vamos colocá-lo outra maneira: é possível saber o tamanho de todos os objetos local para uma função? Eu acho que compilador de otimização não será meu amigo, porque alguns variável irá desaparecer, mas um limite superior é fino.

Foi útil?

Solução

código do kernel Linux é executado em uma pilha 4K em x86. Daí eles se preocupam. O que eles usam para verificar se, é um script perl que escreveu, que você pode encontrar como scripts / checkstack.pl em um tarball do kernel recente (2.6.25 tem isso). Ele é executado na saída do objdump, documentação de uso é no comentário inicial.

Eu acho que eu já utilizado por binários do espaço do usuário idades atrás, e se você conhece um pouco de programação Perl, é fácil de correção que se for quebrado.

De qualquer forma, o que basicamente faz é olhar automaticamente na saída do GCC. E o fato de que hackers do kernel escreveu um desses meios de ferramentas que não há nenhuma maneira estática para fazê-lo com GCC (ou talvez que foi adicionado recentemente, mas eu duvido que isso).

Btw, com objdump do projeto mingw e ActivePerl, ou com Cygwin, você deve ser capaz de fazer isso também no Windows e também em binários obtidos com outros compiladores.

Outras dicas

StackAnlyser parece examinate o próprio código executável além de algumas informações de depuração. O que é descrito por esta resposta , é o que estou procurando, empilhar analisador olhares como um exagero para mim.

Algo semelhante ao que existe para ADA seria ótimo. Olhada nesta página do manual do mosquito manual:

22.2 estática Pilha de Análise de Utilização

Uma unidade compilado com -fstack-uso irá gerar um ficheiro adicional que especifica a quantidade máxima de pilha usada, numa base por função. O arquivo tem o mesmo nome base como o arquivo objeto de destino com uma extensão .su. Cada linha deste arquivo é composto por três campos:

* The name of the function.
* A number of bytes.
* One or more qualifiers: static, dynamic, bounded. 

O segundo campo corresponde ao tamanho da parte conhecida da armação função.

Os meios qualificador estáticos que o tamanho função de quadro é puramente estático. Isso normalmente significa que todas as variáveis ??locais têm um tamanho estático. Neste caso, o segundo campo é uma medida confiável da utilização da pilha função.

Os meios qualificador dinâmicos que o tamanho função de quadro não é estático. Isso acontece principalmente quando algumas variáveis ??locais têm um tamanho dinâmico. Quando esse qualificador aparece sozinho, o segundo campo não é uma medida confiável da análise pilha função. Quando ele é qualificado com delimitada, isso significa que o segundo campo é um máximo de confiança da utilização pilha função.

Eu não vejo por que uma análise estática de código não poderia dar uma figura bom o suficiente para isso.

É trivial para encontrar todas as variáveis ??locais em qualquer função dada, e o tamanho de cada variável pode ser encontrado tanto através do padrão C (para construído em tipos) ou por meio do cálculo lo (para tipos complexos, como estruturas e sindicatos).

Claro, a resposta não pode ser garantido para ser 100% exato, uma vez que o compilador pode fazer vários tipos de otimizações como preenchimento, colocar variáveis ??em registros ou remover completamente as variáveis ??desnecessárias. Mas nenhuma resposta ele dá deve ser uma boa estimativa, pelo menos.

Eu fiz uma rápida pesquisa no Google e encontrou StackAnalyzer mas meu palpite é que outra análise estática de código ferramentas têm capacidades semelhantes.

Se você quer uma figura exata de 100%, então você tem que olhar para a saída do compilador ou verificá-lo durante o tempo de execução (como Ralph sugerido em sua resposta )

Apenas o compilador saberia realmente, uma vez que é o cara que coloca todas as suas coisas juntos. Você teria que olhar para o gerado montagem e ver quanto espaço é reservado no preâmbulo, mas que realmente não são responsáveis ??por coisas como alloca que fazer a sua coisa em tempo de execução.

Assumindo que você está em uma plataforma incorporado, você pode achar que o seu conjunto de ferramentas tem um ir a este. Bons compiladores comerciais incorporados (como, por exemplo, o compilador Arm / Keil), muitas vezes produzir relatórios de utilização da pilha.

Claro, interrupções e recursão são geralmente um pouco além deles, mas ela lhe dá uma idéia aproximada se alguém cometeu um terrível parafuso-up com um tampão de multi megabyte no algum lugar pilha.

Não exatamente "tempo de compilação", mas eu faria isso como uma etapa pós-build:

  • deixar o vinculador cria um arquivo de mapa para você
  • para cada função no arquivo de mapa ler a parte correspondente do executável, e analisar a função prólogo.

Este é semelhante ao que StackAnalyzer faz, mas muito mais simples. Eu acho que analisar o executável ou a desmontagem é a maneira mais fácil que você pode chegar à saída do compilador. Enquanto o compilador sabe essas coisas internamente, eu tenho medo que você não será capaz de obtê-lo a partir dele (que você pode perguntar ao vendedor compilador para implementar a funcionalidade, ou se estiver usando o compilador open source, você poderia fazê-lo sozinho ou deixar alguém fazer isso para você).

Para implementar isso, você precisa:

  • ser capaz de analisar o arquivo mapa
  • compreender o formato do executável
  • saber o que uma função prólogo pode parecer e ser capaz de "decodificar" it

Como fácil ou difícil isso seria depende de sua plataforma de destino. (Embutido? Que arquitetura de CPU? O compilador?)

Tudo isso definitivamente pode ser feito em x86 / Win32, mas se você nunca fez nada assim e tem que criar tudo isso a partir do zero, pode demorar alguns dias antes de terminar e ter algo de trabalho.

Não em geral. O problema da parada em ciência da computação teórica sugere que você não pode sequer prever se um general paradas de programa em uma dada entrada. Calculando a pilha usada para a execução do programa, em geral, seria complicado ainda mais. Então não. Talvez em casos especiais.

Vamos dizer que você tem uma função recursiva cujo nível de recursão depende da entrada que podem ser de comprimento arbitrário e você já está fora de sorte.

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