我经常听到有人说,在编译C和c++程序时,我应该“总是启用编译器警告”。为什么这是必要的?我怎么做呢?
有时我也听到我应该“把警告当作错误”。我应该吗?我怎么做呢?
我经常听到有人说,在编译C和c++程序时,我应该“总是启用编译器警告”。为什么这是必要的?我怎么做呢?
有时我也听到我应该“把警告当作错误”。我应该吗?我怎么做呢?
当前回答
警告包含了一些最熟练的c++开发人员可以放入应用程序中的最佳建议。他们值得留在身边。
C++, being a Turing complete language, has plenty of cases where the compiler must simply trust that you knew what you are doing. 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!). 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. 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.
关闭或忽略警告,就像选择忽略那些比你更有经验的人的免费建议。这是一个傲慢的教训,当你飞得离太阳太近,翅膀融化了,或者发生记忆损坏错误时,这个教训就结束了。在这两者之间,我愿意随时从天上掉下来!
“将警告视为错误”是这一哲学的极端版本。这里的想法是解决编译器给您的每个警告——您听取每个免费建议并执行它。这对你来说是否是一个好的开发模式取决于你的团队以及你所开发的产品类型。这是僧侣可能有的苦行方式。对一些人来说,效果很好。对另一些人来说,则不然。
在我的许多应用程序中,我们不将警告视为错误。我们这样做是因为这些特定的应用程序需要在多个平台上编译,使用多个不同年代的编译器。有时我们会发现,如果在一个平台上修复一个警告,而不将其转化为另一个平台上的警告,实际上是不可能的。所以我们只是小心行事。我们尊重警告,但我们不会为它们竭尽全力。
其他回答
将警告视为错误只有一个问题:当你使用来自其他来源的代码时(例如,微软库,开源项目),他们没有正确地完成他们的工作,编译他们的代码会产生大量的警告。
在编写代码时,我总是确保它不会产生任何警告或错误,并在编译之前进行清理,而不会产生任何无关的噪音。我不得不处理的垃圾让我感到震惊,当我不得不构建一个大项目时,看着一串警告从编译器应该只声明它处理了哪些文件的地方经过时,我感到震惊。
我也记录我的代码,因为我知道软件真正的生命周期成本主要来自维护,而不是最初的编写,但这是另一回事……
你应该总是启用编译器警告,因为编译器经常会告诉你代码哪里出了问题。为此,您将-Wall -Wextra传递给编译器。
您通常应该将警告视为错误,因为警告通常表示您的代码有问题。然而,通常很容易忽略这些错误。因此,将它们视为错误将导致构建失败,因此您不能忽略这些错误。若要将警告视为错误,请将-Werror传递给编译器。
你一定要启用编译器警告,因为一些编译器不擅长报告一些常见的编程错误,包括以下:
初始化变量会被遗忘 从一个被错过的函数返回一个值 printf和scanf族中的简单参数与格式字符串不匹配 函数的使用没有事先声明,尽管这只在C中发生
所以这些函数可以被检测和报告,只是通常不是默认情况;所以这个特性必须通过编译器选项显式地请求。
将警告视为错误只是自律的一种方式:您正在编译一个程序来测试那个闪亮的新功能,但是在您修复那些草率的部分之前,您无法测试。werror提供了其他信息。它只是非常明确地设定了优先级:
在修复现有代码中的问题之前,不要添加新代码
重要的是心态,而不是工具。编译器诊断输出是一种工具。MISRA C(嵌入式C)是另一个工具。使用哪一种并不重要,但可以说编译器警告是最简单的工具(只需设置一个标志),而且信噪比非常高。所以没有理由不使用它。
No tool is infallible. If you write const float pi = 3.14;, most tools won't tell you that you defined π with a bad precision which may lead to problems down the road. Most tools won't raise an eyebrow on if(tmp < 42), even if it's commonly known that giving variables meaningless names and using magic numbers is a way to disaster in big projects. You have to understand that any "quick test" code you write is just that: a test, and you have to get it right before you move on to other tasks, while you still see its shortcomings. If you leave that code as is, debugging it after you spend two months adding new features will be significantly harder.
一旦你进入了正确的心态,使用-Werror就没有意义了。将警告作为警告将允许您做出明智的决定,是否仍然有意义运行您即将开始的调试会话,还是中止它并首先修复警告。
编译器警告是你的朋友
我在传统的Fortran 77系统上工作。编译器告诉我有价值的东西:在子例程调用上的参数数据类型不匹配,如果我有一个变量或子例程参数没有被使用,那么在值被设置到变量之前使用一个局部变量。这些几乎都是错误。
当我的代码编译干净,97%的工作。与我一起工作的另一个人在编译时关闭了所有警告,在调试器中花费数小时或数天,然后让我帮忙。我只是用警告编译他的代码,然后告诉他要修改什么。