本文翻译自:Why should I always enable compiler warnings?
I often hear that when compiling C and C++ programs I should "always enable compiler warnings". 我经常听到,在编译C和C ++程序时,我应该“始终启用编译器警告”。 Why is this necessary? 为什么这是必要的? How do I do that? 我怎么做?
Sometimes I also hear that I should "treat warnings as errors". 有时我也听说我应该“将警告视为错误”。 Should I? 我是不是该? How do I do that? 我怎么做?
#1楼
参考:https://stackoom.com/question/3uhXg/为什么要始终启用编译器警告
#2楼
Why enable warnings? 为什么启用警告?
C and C++ compilers are notoriously bad at reporting some common programmer mistakes by default , such as: 众所周知,C和C ++编译器在默认情况下不善于报告一些常见的程序员错误,例如:
- forgetting to initialise a variable 忘记初始化变量
- forgetting to
return
a value from a function 忘记从函数return
值 - arguments in
printf
andscanf
families not matching the format stringprintf
和scanf
系列中的参数与格式字符串不匹配 - a function is used without being declared beforehand (C only) 使用函数而无需事先声明(仅C)
These can be detected and reported, just usually not by default; 这些可以被检测和报告,通常不是默认情况下; this feature must be explicitly requested via compiler options. 必须通过编译器选项显式请求此功能。
How to enable warnings? 如何启用警告?
This depends on your compiler. 这取决于您的编译器。
Microsoft C and C++ compilers understand switches like /W1
, /W2
, /W3
, /W4
and /Wall
. Microsoft C和C ++编译器了解/W1
, /W2
, /W3
, /W4
和/Wall
类的开关。 Use at least /W3
. 至少使用/W3
。 /W4
and /Wall
may emit spurious warnings for system header files, but if your project compiles cleanly with one of these options, go for it. /W4
和/Wall
可能会为系统头文件发出虚假警告,但是如果您的项目使用以下选项之一进行了正确的编译,则应选择它。 These options are mutually exclusive. 这些选项是互斥的。
Most other compilers understand options like -Wall
, -Wpedantic
and -Wextra
. 其他大多数编译器都可以理解-Wall
, -Wpedantic
和-Wextra
等选项。 -Wall
is essential and all the rest are recommended (note that, despite its name, -Wall
only enables the most important warnings, not all of them). -Wall
是必不可少的,建议所有其他内容使用(请注意,尽管-Wall
有其名称,但它仅启用最重要的警告,而不是全部警告)。 These options can be used separately or all together. 这些选项可以单独使用,也可以一起使用。
Your IDE may have a way to enable these from the user interface. 您的IDE可能有一种从用户界面启用这些功能的方法。
Why treat warnings as errors? 为什么将警告视为错误? They are just warnings! 它们只是警告!
A compiler warning signals a potentially serious problem in your code. 编译器警告表示您的代码中可能存在严重的问题。 The problems listed above are almost always fatal; 上面列出的问题几乎总是致命的。 others may or may not be, but you want compilation to fail even if it turns out to be a false alarm. 其他可能会或可能不会,但是您希望编译失败, 即使事实证明这是一个错误的警报。 Investigate each warning, find the root cause, and fix it. 调查每个警告,找到根本原因,然后加以解决。 In the case of a false alarm, work around it — that is, use a different language feature or construct so that the warning is no longer triggered. 如果发生错误警报,请解决它-即,使用其他语言功能或结构,以便不再触发警告。 If this proves to be very hard, disable that particular warning on a case by case basis. 如果事实证明这很难,请逐个禁用该特定警告。
You don't want to just leave warnings as warnings even if all of them are false alarms. 您不希望仅将警告作为警告,即使它们都是错误警报。 It could be OK for very small projects where the total number of warnings emitted is less than 7. Anything more, and it's easy for a new warning to get lost in a flood of old familiar ones. 对于很小的项目,发出的警告总数少于7个,这可能是可以的。而且,任何其他情况,新的警告很容易在大量老旧的警告中丢失。 Don't allow that. 不要这样 Just cause all your project to compile cleanly. 只需使您的所有项目都能干净地编译即可。
Note this applies to program development. 请注意,这适用于程序开发。 If you are releasing your project to the world in the source form, then it might be a good idea not to supply -Werror
or equivalent in your released build script. 如果要以源代码形式向世界发布项目,那么最好不要在已发布的构建脚本中提供-Werror
或等效内容。 People might try to build your project with a different version of the compiler, or with a different compiler altogether, which may have a different set of warnings enabled. 人们可能会尝试使用不同版本的编译器或完全不同的编译器来构建您的项目,这可能会启用一组不同的警告。 You may want their build to succeed. 您可能希望他们的建造成功。 It is still a good idea to keep the warnings enabled, so that people who see warning messages could send you bug reports or patches. 始终启用警告仍然是一个好主意,以便看到警告消息的人可以向您发送错误报告或补丁。
How to treat warnings as errors? 如何将警告视为错误?
This is again done with compiler switches. 再次使用编译器开关完成此操作。 /WX
is for Microsoft, most others use -Werror
. /WX
适用于Microsoft,其他大多数使用-Werror
。 In either case, the compilation will fail if there are any warnings produced. 无论哪种情况,如果产生任何警告,编译都将失败。
#3楼
C is, famously, a rather low-level language as HLLs go. 众所周知,随着HLL的发展,C是一种相当底层的语言。 C++, though it might seem to be a considerably higher-level language than C, still shares a number of its traits. 尽管C ++似乎比C语言要高级得多,但它仍然具有许多特质。 And one of those traits is that the languages were designed by programmers, for programmers -- and, specifically, programmers who knew what they were doing. 这些特征之一就是这些语言是由程序员设计的,是为程序员而设计的,尤其是那些知道自己在做什么的程序员。
[For the rest of this answer I'm going to focus on C. Most of what I'll say also applies to C++, though perhaps not as strongly. [对于此答案的其余部分,我将重点介绍C。我会说的大多数内容也适用于C ++,尽管可能不那么适用。 Although as Bjarne Stroustrup has famously said, "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." 尽管正如Bjarne Stroustrup所说的那样, “ C使脚上的射击变得容易; C ++使其更难,但是当您这样做时,它会使您的整个腿发疯。” ] ]
If you know what you are doing -- really know what you are doing -- sometimes you may have to "break the rules". 如果您知道自己在做什么- 真的知道自己在做什么-有时您可能必须“违反规则”。 But most of the time, most of us will agree that well-intentioned rules keep us all out of trouble, and that wantonly breaking those rules all the time is a bad idea. 但是大多数时候,我们大多数人都会同意,良好的规则会让我们所有人摆脱困境,并且大胆地始终违反这些规则是一个坏主意。
But in C and C++, there are surprisingly large numbers of things you can do that are "bad ideas" but which aren't formally "against the rules". 但是在C和C ++中,您可以做很多令人惊讶的事情,这些都是“坏主意”,但并不是形式上的“违规”。 Sometimes they're a bad idea some of the time (but might be defensible other times); 有时在某些情况下,这是个坏主意(但在其他时候可能是有道理的); sometimes they're a bad idea virtually all of the time. 有时,几乎所有时间他们都是一个坏主意。 But the tradition has always been not to warn about these things -- because, again, the assumption is that programmers know what they are doing, they wouldn't be doing these things without a good reason, they'd be annoyed by a bunch of unnecessary warnings. 但是传统上一直不对这些事情发出警告-因为再次假设,程序员知道自己在做什么,没有正当的理由他们就不会做这些事情,他们会被一堆烦恼不必要的警告。
But of course not all programmers really know what they're doing. 但是当然,并不是所有的程序员都真正知道自己在做什么。 And, in particular, every C programmer (no matter how experienced) goes through a phase of being a beginning C programmer. 尤其是,每个C程序员(无论经验如何)都经历了成为新手C程序员的阶段。 And even experienced C programmers can get careless and make mistakes. 甚至有经验的C程序员也会变得粗心和犯错。
Finally, experience has shown not only that programmers do make mistakes, but that these mistakes can have real, serious consequences. 最后,经验表明,不仅程序员确实会犯错误,而且这些错误会带来真正的严重后果。 If you make a mistake, and the compiler doesn't warn you about it, and somehow the program doesn't immediately crash or do something obviously wrong because of it, the mistake can lurk there, hidden, sometimes for years, until it causes a really big problem. 如果您犯了一个错误,并且编译器没有警告您,并且由于某种原因程序不会立即崩溃或执行明显错误的操作,那么该错误可能会在那里潜伏,隐藏,有时长达数年,直到导致一个真正的大问题。
So it turns out that, most of the time, warnings are a good idea, after all. 因此,事实证明,在大多数情况下,警告毕竟是个好主意。 Even the experienced programmers have learned (actually, it's " especially the experienced programmers have learned") that, on balance, the warnings tend to do more good than harm. 即便是有经验的程序员也已经学会(实际上,“ 特别是有经验的程序员已经学会”),总的来说,警告往往弊大于利。 For every time you did something wrong deliberately and the warning was a nuisance, there are probably at least ten times you did something wrong by accident and the warning saved you from further trouble. 每次您故意做错了事而警告是令人讨厌的事,您至少有十次无意中做了错事,而警告使您免于进一步的麻烦。 And most warnings can be disabled or worked around for those few times when you really want to do the "wrong" thing. 当您确实想做“错误”的事情时,大多数警告可以禁用或解决几次。
(A classic example of such a "mistake" is the test if(a = b)
. Most of the time, this is a mistake, so most compilers these days warn about it -- some even by default. But if you really wanted to both assign b
to a
and test the result, you can disable the warning by typing if((a = b))
.) (这种“错误”的经典示例是测试if(a = b)
。在大多数情况下,这是一个错误,因此,如今大多数编译器都警告它-甚至在默认情况下也是如此。但是,如果您确实想要要将b
分配给a
并测试结果,可以通过键入if((a = b))
禁用警告。
The second question is, why would you want to ask the compiler to treat warnings as errors? 第二个问题是,为什么要让编译器将警告视为错误? I'd say it's because of human nature, specifically, the all-too-easy reaction of saying "Oh, that's just a warning, that's not so important, I'll clean that up later." 我会说这是由于人的天性,特别是说“哦,那只是一个警告,并不是那么重要,我稍后再整理”的反应太简单了。 But if you're a procrastinator (and I don't know about you, but I'm a terrible procrastinator) it's easy to put off the necessarily cleanup for basically ever -- and if you get into the habit of ignoring warnings, it gets easier and easier to miss an important warning message that's sitting there, unnoticed, in the midst of all the ones you're ignoring. 但是,如果您是拖延症患者(我不知道您是什么,但我是一个糟糕的拖延症患者),则很容易将必要的清理工作推迟到很长一段时间-如果您养成了无视警告的习惯,在您忽略的所有消息之中,越来越容易错过坐在那里的重要警告消息,却未被注意。
So asking the compiler to treat warnings as errors is a little trick you can play on yourself to get around this human foible. 因此,要求编译器将警告视为错误,这是您可以解决这个人为错误的小技巧。
Personally, I'm not as insistent about treating warnings as errors. 就我个人而言,我不太坚持将警告视为错误。 (In fact, if I'm honest, I can say that I virtually never enable that option in my "personal" programming.) But you can be sure I've got that option enabled at work, where our style guide (which I wrote) mandates its use. (实际上,老实说,我可以说我实际上从未在“个人”编程中启用该选项。)但是,您可以确定我在工作时启用了该选项,在我们的样式指南中(写道)要求其使用。 And I would say -- I suspect most professional programmers would say -- that any shop that doesn't treat warnings as errors in C is behaving irresponsibly, is not adhering to commonly-accepted industry best practices. 我想说-我怀疑大多数专业的程序员都会说-任何不将警告视为C错误的车间都是不负责任的行为,没有遵循公认的行业最佳实践。
#4楼
Some warning may mean possible semantic error in code or possible UB. 某些警告可能意味着代码中可能存在语义错误或可能的UB。 Eg ;
例如;
after if()
, unused variable, global variable masked by local, or comparison of signed and unsigned. 在if()
,未使用的变量,局部变量掩盖的全局变量或有符号和无符号的比较。 Many warnings are related to static code analyzer in compiler or to breaches of ISO standard detectable at compile time, which "require diagnostics". 许多警告与编译器中的静态代码分析器有关,或与编译时可检测到的违反ISO标准有关,这些警告“需要诊断”。 While those occurrences may be legal in one particular case, they would be result of design issues most of time. 尽管这些情况在特定情况下可能是合法的,但大多数情况下都是由于设计问题造成的。
Some compilers, eg gcc, have a command line option to activate "warnings as errors" mode, it's a nice , if cruel, tool to educate novice coders. 某些编译器(例如gcc)具有命令行选项来激活“警告为错误”模式,这是一个不错的工具,即使是残酷的教育新手程序员。
#5楼
Take it easy: you don't have to, it is not necessary. 放轻松:您不必,没有必要。 -Wall and -Werror was designed by code-refactoring maniacs for themselves: it was invented by compiler developers to avoid breaking existing builds after compiler updates on the user side . -Wall和-Werror是由代码重构狂为自己设计的: 它是由编译器开发人员发明的,以避免在用户端更新编译器后破坏现有的内部版本 。 The feature is nothing, but all about the decision to break or not to break the build. 该功能什么都不是,而是决定是否中断构建的全部内容。
It is totally up to your preference to use it or not. 是否使用它完全取决于您的偏好。 I use it all the time because it helps me to fix my mistakes. 我一直使用它,因为它可以帮助我纠正错误。
#6楼
Warnings consist of the best advice some of the most skilled C++ developers could bake into an application. 警告包括一些最熟练的C ++开发人员可以融入应用程序的最佳建议。 They're worth keeping around. 他们值得保持。
C++, being a Turing complete language, has plenty of cases where the compiler must simply trust that you knew what you are doing. C ++是一种图灵完整的语言,在很多情况下,编译器必须简单地相信您知道自己在做什么。 However, there are many cases where the compiler can realize that you probably did not intend to write what you wrote. 但是,在许多情况下,编译器可以意识到您可能不打算编写自己编写的内容。 A classic example is printf() codes which don't match the arguments, or std::strings passed to printf (not that that ever happens to me!). 一个典型的例子是与参数不匹配的printf()代码,或者传递给printf的std :: strings(这对我来说从来没有 !)。 In these cases, the code you wrote is not an error. 在这些情况下,您编写的代码不是错误。 It is a valid C++ expression with a valid interpretation for the compiler to act on. 这是一个有效的C ++表达式,带有可让编译器执行的有效解释。 But the compiler has a strong hunch that you simply overlooked something which is easy for a modern compiler to detect. 但是编译器有很强的直觉,您只是忽略了现代编译器易于检测的内容。 These are warnings. 这些是警告。 They are things that are obvious to a compiler, using all the strict rules of C++ at its disposal, that you might have overlooked. 对于编译器而言,它们是显而易见的事情,因为使用了可能会忽略的C ++的所有严格规则。
Turning warnings off, or ignoring them, is like choosing to ignore free advice from those more skilled than you. 关闭或忽略警告就像选择忽略那些比您熟练的人提供的免费建议。 Its a lesson in huberis that ends either when you fly too close to the sun and your wings melt, or a memory corruption error occurs. 这是在胡贝里斯上的一课,当您太靠近太阳飞行并且翅膀融化或发生内存损坏错误时,该课程就会结束。 Between the two, I'll take falling from the sky any day! 在这两者之间,我每天都会从天上掉下来!
"Treat warnings as errors" is the extreme version of this philosophy. “将警告视为错误”是这种理念的极端版本。 The idea here is that you resolve every warning the compiler gives you -- you listen to every bit of free advice and act on it. 这里的想法是,您解决编译器给您的每条警告-您听取每条免费建议,并采取相应措施。 Whether this is a good model for development for you depends on the team and what kind of product you are working on. 对于您来说,这是否是一个好的开发模型取决于团队和正在开发哪种产品。 It's the ascetic approach that a monk might have. 这是和尚可能会采取的禁欲法。 For some, it works great. 对于某些人来说,它很棒。 For others, it does not. 对于其他人则不是。
On many of my applications we do not treat warnings as errors. 在我的许多应用程序中,我们都不将警告视为错误。 We do this because these particular applications need to compile on several platforms with several compilers of varying ages. 我们这样做是因为这些特定的应用程序需要在具有不同年龄的多个编译器的多个平台上进行编译。 Sometimes we find it is actually impossible to fix a warning on one side without it turning into a warning on another platform. 有时,我们发现实际上不可能在不将警告变成另一平台的警告的情况下将警告固定在一侧。 So we are merely careful. 所以我们只是小心。 We respect warnings, but we don't bend over backwards for them. 我们尊重警告,但我们不会向后弯腰。