Além da configuração -Wall
e da configuração -std=XXX
, que outros sinalizadores de compilador realmente úteis, mas menos conhecidos, existem para uso em C?
Estou particularmente interessado em avisos adicionais e / ou em transformar avisos em erros em alguns casos para minimizar absolutamente qualquer incompatibilidade acidental de tipo.
c
gcc
compiler-flags
Matt Joiner
fonte
fonte
-save-temps
,-Wshadow
e-fmudflap
foram as melhores descobertas que eu não conhecia, graças a todos.gcc -c [flags-go-here] -o myprog.o myprog.c
para compilar (não vincular) um programa em C.Respostas:
Várias
-f
opções de geração de código são interessantes:A
-ftrapv
função fará com que o programa seja interrompido por excesso de número inteiro assinado (formalmente "comportamento indefinido" em C).-fverbose-asm
é útil se você estiver compilando-S
para examinar a saída do assembly - ele adiciona alguns comentários informativos.-finstrument-functions
adiciona código para chamar funções de criação de perfil fornecidas pelo usuário em cada ponto de entrada e saída de função.fonte
-ftrapv
, dê uma olhada aqui stackoverflow.com/questions/20851061/… .. parece que há um bug que está há muito tempo aguardando para ser corrigido.Aqui estão os meus:
-Wextra
,-Wall
: essencial.-Wfloat-equal
: útil, porque geralmente testar números de ponto flutuante quanto à igualdade é ruim.-Wundef
: avisa se um identificador não inicializado é avaliado em uma#if
diretiva.-Wshadow
: avisa sempre que uma variável local sombreia outra variável local, parâmetro ou variável global ou sempre que uma função interna é sombreada.-Wpointer-arith
: avisa se alguma coisa depende do tamanho de uma função ou devoid
.-Wcast-align
: avisa sempre que um ponteiro é convertido, de modo que o alinhamento necessário do alvo seja aumentado. Por exemplo, avise se achar *
é convertido em umaint *
máquina em que números inteiros só podem ser acessados em limites de dois ou quatro bytes.-Wstrict-prototypes
: avisa se uma função é declarada ou definida sem especificar os tipos de argumento.-Wstrict-overflow=5
: avisa sobre casos em que o compilador otimiza com base na suposição de que o estouro assinado não ocorre. (O valor 5 pode ser muito rigoroso, consulte a página do manual.)-Wwrite-strings
: dê às constantes da string oconst char[
comprimento do tipo]
para que a cópia do endereço de uma para um nãoconst char *
ponteiro receba um aviso.-Waggregate-return
: avisa se alguma função que retorna estruturas ou uniões é definida ou chamada.-Wcast-qual
: avisa sempre que um ponteiro é convertido para remover um qualificador de tipo do tipo de destino * .-Wswitch-default
: avisa sempre que umaswitch
instrução não tem umdefault
caso * .-Wswitch-enum
: avisa sempre que umaswitch
instrução possui um índice do tipo enumerado e não possui umcase
para um ou mais dos códigos nomeados dessa enumeração * .-Wconversion
: avise sobre conversões implícitas que podem alterar um valor * .-Wunreachable-code
: avisa se o compilador detectar que o código nunca será executado * .Os marcados com * às vezes dão muitos avisos falsos, então eu os uso conforme a necessidade.
fonte
-Wformat=2
: Verificações de formato extra nas funções printf / scanf.-Wall
?-Wwrite-strings
porque eu odeio muito.-Wwrite-strings
especificamente diz que não faz parte de-Wall
: gcc.gnu.org/onlinedocs/gcc/… . Talvez algo mais na sua configuração esteja definindo esse sinalizador? Ou talvez você esteja compilando C ++?Sempre usar
-O
ou acima (-O1
,-O2
,-Os
, etc.). No nível de otimização padrão, o gcc busca a velocidade de compilação e não faz análises suficientes para avisar sobre coisas como variáveis unitizadas.Considere fazer
-Werror
política, pois os avisos que não param a compilação tendem a ser ignorados.-Wall
praticamente ativa os avisos que provavelmente são erros.Os avisos incluídos
-Wextra
tendem a sinalizar códigos comuns e legítimos. Eles podem ser úteis para revisões de código (embora os programas no estilo fiapo achem muito mais armadilhas são mais flexíveis), mas eu não os ativaria para o desenvolvimento normal.-Wfloat-equal
é uma boa idéia se os desenvolvedores do projeto não estiverem familiarizados com o ponto flutuante e uma má idéia se estiverem.-Winit-self
é útil; Eu me pergunto por que não está incluído-Wuninitialized
.-Wpointer-arith
é útil se você tiver um código principalmente portátil que não funcione-pedantic
.fonte
Isso deixa para trás os resultados do pré-processador e da montagem.
A fonte pré-processada é útil para depurar macros.
A montagem é útil para determinar quais otimizações entraram em vigor. Por exemplo, convém verificar se o GCC está otimizando a chamada de cauda em algumas funções recursivas, pois sem ela você pode potencialmente sobrecarregar a pilha.
fonte
Estou surpreso que ninguém tenha dito isso ainda - o sinalizador mais útil para mim é
-g
que coloca as informações de depuração no executável, para que você possa depurá-las e percorrer a fonte (a menos que seja proficiente e esteja lendo a montagem e como ostepi
comando) de um programa enquanto estiver em execução.fonte
-fmudflap - adiciona verificações de tempo de execução a todas as operações arriscadas do ponteiro para capturar o UB. Isso efetivamente imuniza seu programa novamente, estouros de buffer e ajuda a capturar todos os tipos de ponteiros pendentes.
Aqui está uma demonstração:
fonte
-fmudflap
não é mais suportado desde o GCC 4.9, você recebewarning: switch '-fmudflap' is no longer supported
. Foi substituído pelo AddressSanitizer.Não é realmente relacionado ao C / C ++, mas é útil de qualquer maneira:
Coloque todos os sinalizadores válidos acima (todos que você especificou) em um 'arquivo' e use este sinalizador acima para usar todos os sinalizadores nesse arquivo juntos.
por exemplo:
Arquivo: compilerFlags
Em seguida, compile:
fonte
-march=native
para produzir código otimizado para a plataforma (= chip) na qual você está compilandofonte
Se você precisar conhecer os sinalizadores de pré-processador predefinidos pelo compilador:
fonte
Não é realmente útil para detectar erros, mas a
-masm=intel
opção raramente mencionada torna o uso-S
a inspeção do resultado da montagem seja muito mais agradável.A sintaxe da montagem da AT&T machuca minha cabeça demais.
fonte
Meu makefile normalmente contém
As mais importantes dessas opções já foram discutidas antes, por isso vou apontar os dois recursos que ainda não foram apontados:
Mesmo trabalhando em uma base de código que precisa ser C simples para portabilidade para alguma plataforma que ainda não possui um compilador C ++ decente, eu faço uma compilação "extra" com o compilador C ++ (além do compilador C). Isso tem três benefícios:
Sim, sou uma Pollyanna irremediavelmente otimista que fica pensando que certamente a qualquer mês, agora que uma plataforma será declarada obsoleta ou ganhará um compilador C ++ decente, e finalmente podemos mudar para C ++. Na minha opinião, é inevitável - a única questão é se isso acontece antes ou depois da administração finalmente emitir um pônei para todos. :-)
fonte
fonte
-Wold-style-definition
se você precisar lidar com reincidentes que pensam que as funções do estilo K&R são uma boa idéia, mesmo com declarações com protótipos. (Eu tenho que lidar com pessoas assim. Realmente me irrita quando encontro um novo código escrito em K&R. Já é ruim o suficiente ter material K&R herdado que não é fixo, mas novo código! Grump !!!)Aqui está uma grande bandeira que não foi mencionada:
Dê um erro sempre que uma função for usada antes de ser declarada.
fonte
O manual está cheio de sinalizadores interessantes com boas descrições. No entanto, -Wall provavelmente tornará o gcc o mais detalhado possível. Se você deseja dados mais interessantes, consulte o valgrind ou alguma outra ferramenta para verificar se há erros.
fonte
man gcc | nl
relata mais de 11000 linhas. Isso é mais do que a infame página debash
manual!Bem, também
-Wextra
deve ser padrão.-Werror
transforma avisos em erros (o que pode ser muito irritante, especialmente se você compilar sem-Wno-unused-result
).-pedantic
em combinação comstd=c89
fornece avisos adicionais se você usar os recursos do C99.Mas é isso aí. Você não pode ajustar um compilador C em algo mais salvo em tipo do que o próprio C.
fonte
-M*
família de opções.Isso permite que você escreva arquivos make que descobrem automaticamente em quais arquivos de cabeçalho seus arquivos de origem c ou c ++ devem depender. O GCC gerará arquivos make com essas informações de dependência e você os incluirá em seu arquivo make principal.
Aqui está um exemplo de um makefile extremamente genérico usando -MD e -MP que irá compilar um diretório cheio de arquivos de código-fonte e cabeçalho c ++ e descobrir todas as dependências automaticamente:
Aqui está uma postagem de blog que discute isso em mais profundidade: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html
fonte
Existe
-Werror
, que trata todos os avisos como erros e interrompe a compilação. Agcc
página do manual explica cada opção de linha de comando para o seu compilador.fonte
gcc
sinalizadores podem ser diferentes entre os seus e o link que alguém possa sugerir. É por isso que as páginas de manual são fornecidas com o seu software.-Wfloat-equal
De: http://mces.blogspot.com/2005/07/char-const-argv.html
fonte
Encontrei este tópico procurando por um sinalizador para corrigir um problema específico, não o vejo aqui, então vou adicionar um que estava me impressionando na minha postagem :
A
-Wformat=2
bandeiraE a parte realmente importante sobre isso (de acordo com o manual do GCC ):
Então, só porque você tem
-Wall
, não significa que você tem tudo. ;)fonte
Às vezes eu uso
-s
para um executável muito menor:Fonte: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
fonte
strip
no seu binário, assim você pode ter um binário com informações de depuração, removê-lo mais tarde para distribuição.strip
funciona também, mas-s
pode ser mais rápido e mais fácil, embora não seja tão elaborado como correrstrip
Embora essa resposta possa ser um pouco fora do tópico e a pergunta seja um +1 digno de mim, pois
existe uma ferramenta que deve detectar TODOS os erros e possíveis erros que podem não ser óbvios; existe uma tala que IMHO faz um trabalho muito melhor na detecção de erros em comparação com o gcc ou qualquer outro compilador. Essa é uma ferramenta digna de ter no seu baú de ferramentas.A verificação estática por meio de uma ferramenta do tipo fiapo, como o splint, deveria ter sido parte de uma cadeia de ferramentas do compilador.
fonte
Além de
-Wall
, a opção-W
ou-Wextra
(-W
funciona com versões mais antigas do gcc e com as mais recentes; versões mais recentes suportam o nome alternativo-Wextra
, o que significa a mesma coisa, mas é mais descritivo) permite vários avisos adicionais.Também há ainda mais avisos que não são ativados por nenhum deles, geralmente para coisas que são mais questionáveis. O conjunto de opções disponíveis depende de qual versão do gcc você está usando - consulte
man gcc
ouinfo gcc
para obter detalhes, ou consulte a documentação on - line da versão específica do gcc em que está interessado. E-pedantic
emite todos os avisos exigidos pelo padrão em particular (que depende em outras opções como-std=xxx
ou-ansi
) e reclama do uso de extensões gcc.-Werror
transforma todos os avisos em erros. Eu não acho que o gcc permita que você faça isso seletivamente para avisos específicos, no entanto.Você provavelmente descobrirá que precisa ser seletivo sobre quais avisos são ativados por projeto (especialmente se você usar
-Werror
), pois os arquivos de cabeçalho de bibliotecas externas podem disparar alguns deles. (-pedantic
em particular, tende a ser inútil a esse respeito, na minha experiência.)fonte
-Werror=some-warning
.-Wmissing-prototypes
: Se uma função global for definida sem uma declaração de protótipo anterior.-Wformat-security
: Avisa sobre o uso de funções de formato que representam possíveis problemas de segurança. No momento, isso avisa sobre chamadasprintf
escanf
funções em que a cadeia de formato não é literal e não há argumentos de formatofonte
-Werror=return-type
: Aplica erro quando a função não tem retorno no gcc. Está/we4716
no Visual Studio.-Werror=implicit-function-declaration
: Aplica erro quando a função é usada sem definida / não incluída. Está/we4013
no Visual Studio.-Werror=incompatible-pointer-types
: Erro inicial quando o tipo de um ponteiro não corresponde ao tipo de ponteiro esperado. Está/we4133
no Visual Studio.Na verdade, eu gostaria de manter meu código C em várias plataformas e uso o CMake, e coloquei os cflags fornecidos no CMakeLists.txt como:
fonte