Freqüentemente, em C abaixo gcc
, começarei com o seguinte conjunto de sinalizadores de aviso (dolorosamente reunidos de várias fontes):
-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi
Eu construirei (pelo menos minhas versões de depuração) com esse conjunto de avisos e corrigirei tudo o que for possível (geralmente tudo) e removerei os sinalizadores apenas se não forem relevantes ou não corrigíveis (quase nunca é o caso). Às vezes, também adicionarei -Werror
se precisar me afastar durante a compilação.
Estou apenas aprendendo C ++ (sim, tenho 15 anos de atraso) e gostaria de começar com o pé direito.
Minha pergunta é: Alguém tem um conjunto semelhante pré-compilado de sinalizadores de aviso completos para C ++ em g++
? (Eu sei que muitos deles serão os mesmos.)
-Wall
) é uma-Wbloody_everything
bandeira :-)-Weverything
. Eu li que mesmo os desenvolvedores do Clang ++ estão um pouco preocupados com os usuários ativando-o; aparentemente, ele foi projetado apenas para uso em desenvolvimento interno. Porém, isso não faz sentido, porque ativar-Weverything
é provavelmente a melhor maneira possível de descobrir avisos potencialmente úteis que você não conhecia antes.Respostas:
Examinei e encontrei o conjunto mínimo de inclusões que deveria receber o nível máximo de aviso. Em seguida, removi dessa lista o conjunto de avisos que, na verdade, não indicam que algo de ruim está acontecendo, ou então há muitos falsos positivos para serem usados em uma compilação real. Comentei por que todos os que excluí foram excluídos. Este é o meu conjunto final de avisos sugeridos:
-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused
Avisos questionáveis presentes:
Incluo
-Wno-unused
porque geralmente tenho variáveis que sei que usarei mais tarde, mas ainda não tenho a funcionalidade escrita. A remoção de avisos sobre isso me permite escrever no meu estilo preferido de adiar ocasionalmente a implementação das coisas. É útil desativá-lo de vez em quando para garantir que nada escorregue pelas rachaduras.-Wdisabled-optimization
parece uma forte configuração de preferência do usuário. Acabei de adicionar este à minha compilação (apenas para compilações otimizadas por razões óbvias) e ele não apareceu nada, por isso não parece ser um aviso especialmente falador, pelo menos pela maneira como codifico. Eu o incluo (mesmo que o código que aciona esse aviso não esteja necessariamente errado) porque acredito em trabalhar com minhas ferramentas em vez de contra elas. Se o gcc está me dizendo que não pode otimizar o código da maneira como o escrevi, então devo reescrevê-lo. Suspeito que o código que aciona esse aviso possa se beneficiar de ser mais modular, independentemente, portanto, embora o código não esteja tecnicamente errado (provavelmente), estilisticamente é provável.-Wfloat-equal
alerta para comparações de igualdade seguras (em particular, comparação com um valor não calculado de -1). Um exemplo no meu código em que eu uso isso é que eu tenho um vetor de float. Eu passo por esse vetor e há alguns elementos que ainda não posso avaliar o que deveriam ser, então os defino como -1.0f (já que meu problema usa apenas números positivos, -1 está fora do domínio). Mais tarde, passo a atualizar os valores -1.0f. Não se presta facilmente a um método de operação diferente. Eu suspeito que a maioria das pessoas não tenha esse problema, e a comparação de um número exato em ponto flutuante provavelmente é um erro, por isso estou incluindo-o na lista padrão.-Wold-style-cast
tem muitos falsos positivos no código da biblioteca que estou usando. Em particular, a família de funções htonl usada nas redes, bem como a implementação de criptografia Rijndael (AES) que estou usando, tem moldes no estilo antigo que me alertam. Pretendo substituir os dois, mas não tenho certeza se há mais alguma coisa no meu código sobre a qual ele reclamará. A maioria dos usuários provavelmente deve ter isso por padrão, no entanto.-Wsign-conversion
foi difícil (e quase não entrou na lista). Ativá-lo no meu código gerou uma enorme quantidade de avisos (mais de 100). Quase todos eles eram inocentes. No entanto, tomei o cuidado de usar números inteiros assinados sempre que não tivesse certeza, embora, para meu domínio de problema específico, normalmente recebesse um ligeiro aumento de eficiência usando valores não assinados devido à grande quantidade de divisão de números inteiros que faço. Eu sacrifiquei essa eficiência porque estava preocupado em promover acidentalmente um número inteiro assinado para um não assinado e depois dividi-lo (o que não é seguro, ao contrário da adição, subtração e multiplicação). Ativar esse aviso me permitiu alterar com segurança a maioria das minhas variáveis para tipos não assinados e adicionar algumas transmissões em outros lugares. Atualmente, é um pouco difícil de usar, porque o aviso não é tão inteligente. Por exemplo, se você fizerunsigned short + (integral constant expression)
, esse resultado é implicitamente promovido para int. Em seguida, ele avisa sobre um possível problema de sinal se você atribuir esse valor aunsigned
ouunsigned short
, mesmo que seja seguro. Esse é definitivamente o aviso mais opcional para quase todos os usuários.-Wsign-promo
: veja-Wsign-conversion
.-Wswitch-default
parece inútil (você nem sempre quer um caso padrão se tiver enumerado explicitamente todas as possibilidades). No entanto, ativar esse aviso pode aplicar algo que provavelmente é uma boa ideia. Nos casos em que você deseja explicitamente ignorar tudo, exceto as possibilidades listadas (mas outros números são possíveis), insiradefault: break;
para torná-lo explícito. Se você enumerar explicitamente todas as possibilidades, ativar esse aviso ajudará a garantir algo como assert (false) para garantir que você realmente cobriu todas as opções possíveis. Ele permite que você seja explícito em qual é o domínio do seu problema e o imponha programaticamente. No entanto, você terá que ter cuidado em apenas afirmar (false) em qualquer lugar. É melhor do que não fazer nada com o caso padrão, mas, como de costume com assert, ele não funcionará nas versões do release. Em outras palavras, você não pode confiar nele para validar os números obtidos de, digamos, uma conexão de rede ou um banco de dados sobre o qual você não tem controle absoluto. Exceções ou retorno antecipado são a melhor maneira de lidar com isso (mas ainda exigem que você tenha um caso padrão!).-Werror
é importante para mim. Ao compilar grandes quantidades de código em uma compilação multithread com vários destinos, é fácil passar um aviso. Transformar avisos em erros garante que eu os observe.Depois, há um conjunto de avisos que não estão incluídos na lista acima porque eu não achei que fossem úteis. Estes são os avisos e meus comentários sobre por que não os incluo na lista padrão:
Avisos ausentes:
-Wabi
não é necessário porque não estou combinando binários de diferentes compiladores. Tentei compilar com ele de qualquer maneira, e não foi acionado, por isso não parece desnecessariamente detalhado.-Waggregate-return
não é algo que eu considere um erro. Por exemplo, ele é acionado ao usar um loop for baseado em intervalo em um vetor de classes. A otimização do valor de retorno deve cuidar de quaisquer efeitos negativos disso.-Wconversion
aciona esse código:short n = 0; n += 2;
a conversão implícita em int causa um aviso quando é convertida novamente em seu tipo de destino.-Weffc++
inclui um aviso se todos os membros dos dados não forem inicializados na lista de inicializadores. Intencionalmente não faço isso em muitos casos, portanto o conjunto de avisos é muito confuso para ser útil. É útil ativar de vez em quando e procurar outros avisos (como destruidores não virtuais de classes base). Isso seria mais útil como uma coleção de avisos (como-Wall
) em vez de um único aviso por si só.-Winline
está ausente porque eu não uso a palavra-chave inline para fins de otimização, apenas para definir funções inline nos cabeçalhos. Não me importo se o otimizador realmente o alinha. Esse aviso também se queixa se não conseguir incorporar uma função declarada em um corpo de classe (como um destruidor virtual vazio).-Winvalid-pch
está ausente porque eu não uso cabeçalhos pré-compilados.-Wmissing-format-attribute
não é usado porque eu não uso extensões gnu. Mesmo para-Wsuggest-attribute
e vários outrosPotencialmente notável por sua ausência é
-Wno-long-long
, da qual eu não preciso. Eu compilo com-std=c++0x
(-std=c++11
no GCC 4.7), que incluilong long
tipos inteiros. Os que estão presos no C ++ 98 / C ++ 03 podem considerar adicionar essa exclusão da lista de avisos.-Wnormalized=nfc
já é a opção padrão e parece ser a melhor.-Wpadded
é ativado ocasionalmente para otimizar o layout das classes, mas não é ativado porque nem todas as classes têm elementos suficientes para remover o preenchimento no final. Em teoria, eu poderia obter algumas variáveis extras para 'free', mas não vale a pena o esforço extra de manter isso (se o tamanho da minha classe mudar, não é fácil remover essas variáveis anteriormente livres).-Wstack-protector
não é usado porque eu não uso-fstack-protector
-Wstrict-aliasing=3
está ativado-Wall
e é o mais preciso, mas parece que os níveis 1 e 2 dão mais avisos. Em teoria, um nível mais baixo é um aviso "mais forte", mas custa mais falsos positivos. Meu próprio código de teste compilado de forma limpa em todos os três níveis.-Wswitch-enum
Não é um comportamento que eu quero. Não quero lidar com todas as instruções de switch explicitamente. Seria útil se o idioma tivesse algum mecanismo para ativar isso em instruções de chave especificadas (para garantir que futuras alterações na enum sejam tratadas em todos os lugares que elas precisam estar), mas é um exagero para uma configuração de "tudo ou nada".-Wunsafe-loop-optimizations
causa muitos avisos espúrios. Pode ser útil aplicar este periodicamente e verificar manualmente os resultados. Como exemplo, ele gerou esse aviso no meu código quando fiz um loop sobre todos os elementos em um vetor para aplicar um conjunto de funções a eles (usando o loop for baseado em intervalo). Também é um aviso para o construtor de uma matriz const de const std :: string (onde não há loop no código do usuário).-Wzero-as-null-pointer-constant
e-Wuseless-cast
são apenas avisos do GCC-4.7, que adicionarei quando passar para o GCC 4.7.Arquivei alguns relatórios de bugs / solicitações de aprimoramento no gcc como resultado de algumas dessas pesquisas. Espero que, eventualmente, eu possa adicionar mais avisos da lista "não incluir" na lista "incluir" . Esta lista inclui todos os avisos mencionados neste tópico (além de alguns extras). Muitos dos avisos não mencionados explicitamente nesta postagem estão incluídos como parte de outro aviso que menciono. Se alguém perceber completamente quaisquer avisos excluídos desta postagem, entre em contato.
edit: Parece que eu perdi vários (que eu adicionei agora). Na verdade, existe uma segunda página em http://gcc.gnu.org que está muito bem oculta. Opções gerais de aviso e opções C ++ (role para baixo até o final para obter avisos)
fonte
-Wswitch-enum
avisa se você não manipula explicitamente todos os valores de enumeração em uma opção edefault
não conta como explícito. Por outro lado,-Wswitch-default
avisa se o seu switch não possui umdefault
caso, mesmo que você tenha explicitamente coberto todos os valores possíveis.-isystem
, em vez de-I
no seu "código da biblioteca de idade" para evitar todos esses falsos positivosAh, todas as minhas pesquisas originais exibiram 99% das postagens sobre como suprimir avisos (assustadoramente), mas acabei de passar por esse comentário , que tem esse adorável conjunto de sinalizadores (alguns menos relevantes):
Cruzado com:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Então, acho que esse é um bom ponto de partida. Não percebeu que aquilo era um engodo, mas pelo menos estava profundamente enterrado. :-)
fonte
-Wall
não faça o que seria de esperar. Mas obrigado, alguns deles parecem muito úteis!-Waggregate-return
? Isso me dá um aviso para cada uso debegin/end()
Alguns deles já estão incluídos no
-Wall
ou-Wextra
.Uma boa configuração básica para C é:
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
e para C ++
-ansi -pedantic -Wall -Wextra -Weffc++
(pulando
-Werror
para C ++, pois-Weffc++
tem alguns aborrecimentos)fonte
-std=c89
. No modo C ++, é equivalente a-std=c++98
. ou seja, se você está especificando algum outrostd
, o uso não façaansi
Experimentar
É um começo rápido e sujo, que definitivamente precisará de alguns ajustes; por um lado, mesmo se você chamar o compilador pelo nome apropriado para o seu idioma (por exemplo,
g++
para C ++), você receberá avisos que não se aplicam a esse idioma (e o compilador levantará as mãos e se recusará a continuar até que você remova o aviso).Outra coisa é que eu adicionei
-Werror
, porque se você não está corrigindo os avisos, por que se importa em ativá-los? Você também pode retirar avisos da lista. (Por exemplo, quase nunca uso-Waggregate-return
com C ++.)Alguns avisos não farão nada sem outras opções relacionadas ao desempenho (
-Wstack-protector
).-fdiagnostics-show-option
e o manual do GCC são seus amigos.A propósito, alguns avisos são mutuamente exclusivos; em particular, usando
-Wtraditional
e-Wold-style-definition
junto com-Werror
, não será compilado.fonte
Em CmakeLists.txt do meu Clion
fonte