3

这个问题不是特定于C++,只是使用C++的东西作为例子。为什么在第三方代码中没有警告时,不要将所有警告视为错误?

一个普遍的观点是,“将所有警告视为错误”(如/WX Visual C++选项)是好的,因为a warning is a bug waiting to happen(顺便说一句,链接线程充满了“我的目标为零警告”语句)。

到目前为止,我所看到的唯一反驳是某些第三方代码不会在没有警告的情况下编译。

好吧,让我们对这个问题的持续时间假装编译器的一些代码暂时禁用警告方式(这样的事情在Visual C++):

#pragma warning(push) 
#pragma warning(disable:X) 
#include <ThirdParty.h> 
#pragma warning(pop) 

,然后第三方代码是不是问题了。

假设我们完全控制了所有的代码(没有第三方,或者我们可以在第三方代码中禁用警告),那么不将警告视为错误的原因是什么?

回答

6

因为有时候你比编译器知道得更好。

现代编译器并不一定经常使用,但有些时候您需要稍微在规范之外做某些事情,或者对类型有点棘手,并且在这种特殊情况下它是安全的,但不正确。这会引起警告,因为从技术上讲,在某些时候它通常大部分都是错误的,并且编译器会付钱告诉你什么时候你可能是错的。

它似乎归结为编译器通常知道最好的,但并不总是看到整个图片或知道你的意思是。有些时候警告是不是错误,不应该被视为一个。

当你偏离标准使用时,说挂钩功能和重写代码在内存中,不准确的警告变得更常见。编辑导入表或模块结构可能涉及一些可能看起来有点滑稽的指针算术,因此您会收到警告。

另一个可能的情况是,当您使用编译器给出警告的非标准功能时。例如,在MSVC10中,此:

enum TypedEnum : int32_t 
{ 
    ... 
}; 

将给出非标准的扩展警告。编码到编译器时完全有效的代码,但仍会触发警告(我相信在级别4下)。现在在C++ 11中的许​​多功能以前是作为特定于编译器的功能实现的,它们将遵循这一点(完全安全,完全有效,仍然是警告)。

,给出了一个警告,强制值bool,像另一个安全的情况下:

bool FlagSet(FlagType flags) { return (flags & desired); } 

这给出了一个性能警告。如果你知道你想要的,并且不会导致性能下降,那么警告是无用的,但仍然存在。

现在,这是一个粗略的,因为你可以很容易地编码,但是这引出了另一个观点:可能有时候有两种不同的方法来做同样的结果,速度和可靠性,但只有一个不太可读,另一个不太正确。您可以在正确的代码上选择更干净的代码并发出警告。

还有其他情况下可能发生的潜在问题,其中警告解决。例如,MSVC C4683的描述字面意思是“在......时谨慎操作”。这是一个经典的词语警告,可能会发生一些不好的事情。如果你知道你在做什么,它不适用。

其中大多数都有一些替代代码风格或编译器提示来禁用警告,但不需要关闭警告。

就我个人而言,我发现打开警告然后修复它们有助于摆脱大多数小错误(错别字,类似的东西)。但是,有些地方编译器不喜欢某种特定方式的必须执行的操作,而这正是警告错误的地方。

+3

另一方面,如果您真的需要解决这个问题,则总是可以通过编译指示取消特定警告。它也为维护人员记录了一些棘手的问题。 –

+0

@MatthieuM。在我的阅读中,这是一个问题。也许我误解了它。最小的范围当然是最好的*当禁用警告(-as-error)时*,我不会为整个项目推荐这么做。 – ssube

4

我见过3个原因:

  • 遗留代码:这是一个非常艰巨的任务采取的是充满了被警告,并慢慢地更新它,这样它的相容代码。作为任何修改,存在引入新bug的风险。有时潜在的好处是不值得的风险。无知:通常不是一个明智的决定,许多人不会摆弄编译器设置
  • 懒惰:又名,在地毯下扫视,希望只在业余爱好项目上采用(我很乐观,我很乐观,我很乐观......)

的遗留代码当然是一个问题,但它可以有效地处理:

  • 处理遗留代码作为第三方代码(又名中国长城)
  • 改革的代码,同时任意一个文件(使用“UglyWarningDeactivator.h”对于非改性的)或一次一个警告(通过选择性地使他们)

的长城战略当测试与代码一样糟糕或时间稀少时最好使用。否则,当资源和测试可信度允许时,我显然会敦促您采取增量重写方法。


在新的代码库上?没有理由。在最糟糕的情况下,如果你真的需要一些棘手的东西(输入惩罚,...),你总是可以有选择地停用相关代码区域的警告。真正伟大的是,它证明了可怕的事情正在发生!

2

我非常喜欢使用一个代码库来编写一些警告,而不是那些警告生成代码由于某些“不可协商”警告被关闭而被激活的警告(我不会假装这个不会发生)。至少在前一种情况下,可能需要一些代码审查的区域仅通过重建就可以清楚地看到。

此外,具有致命/警告/良性三种类别允许很多范围将有用信息的微小位添加到警告类别(请参阅C4061),而不会破坏构建。只有一个致命或不重要的区别,警告列表将不得不更加明智。

1

在许多情况下,一个程序集中的更改或语言的更改可能导致用于干净地编译的代码开始发出警告。在某些情况下,临时容忍此类警告可能比要求在进行任何可测试之前执行所有必要的编辑以消除这些警告更好。

4

我不同意断言“没有理由”。

我个人认为正确的做法是零警告政策,但不会将警告视为错误。我的断言是,这增加了程序员的生产力和责任。

我已经在团队中完成了两种方法:1)警告作为错误,2)作为策略的零警告,但没有被编译器强制执行。在这两种情况下,发布都没有任何警告,警告级别保持在零。然而,在后一种情况下,偶尔会有一些国家的警告水平在短时间内上升到极少数。

这导致了更高质量的代码和更好的团队。看看我会如何尝试从记忆中提出一个合理的例子。如果你有足够的聪明和动力,你就可以打洞,但是试图展现你的记忆力和想象力,我认为你会明白我的观点,不管我的例子中有什么缺陷。

比方说,您有一些遗留的c风格的代码,它们一直在使用signed-ints进行索引编制,并使用负面情况进行某种特殊处理。您想要使代码现代化以利用std算法,也许可以通过boost来提供。您修复了代码的一个角落,这是一个很好的概念证明,所以您想将它添加到代码审查堆栈中,因为您确定要以这种方式完成整个任务。

最终签名的东西会消失,但此时您会收到警告,表明您比较了签名和未签名的整数。如果您的公司正在执行免警告构建,您可以:

  1. 要static_casting。
  2. 介绍一些不必要的临时代码。
  3. 大爆炸 - 一次性移动整个事物。

同样的事情发生的原因很多。所有这些都不如推出一些警告,在你的团队会议上讨论警告,并在接下来的几周内的某个时候清理它们。铸造和临时代码会在未来几年中徘徊并污染代码,而在有动力的团队中跟踪警告将会很快得到清理。

在这一点上,有些人会声称“是的,但人们不会有足够的动机”或“不是我的团队,他们都是废话”等等(至少我经常听到这些论点)。我发现这通常是Fundamental attribution error的一个例子。如果你对待你的同事是不负责任的,不加理睬的,他们会倾向于这样做。

虽然有大量的社会科学来支持,但我只能提供我的个人经验,当然这是轶事。我曾在两个团队工作,我们从大量遗留代码库和大量警告(数千个)开始。这是一个可怕的情况,可以肯定。除了成千上万的警告之外,还有更多的警告被忽略,因为这会污染编译器输出太多。

队1:警告的警告,但不能耐受

在组1中,我们跟踪的詹金斯警告#,并在我们的弱小组会议,我们谈到了警告的数量在干什么。这是一个5人队,其中我们两个真正关心。当我们中的一个人降低警告水平时,另一个人会在会议上唱赞歌。清理警告消除了未发现的错误时,我们宣传了这一事实。在其他5位编码员中的2位加入后几个月后,我们很快(在一年内)将警告降至零。警告不时会在几十年或二十年中逐渐升高。当发生这种情况时,负责的开发人员会进来说声抱歉,并解释他们为什么在那里以及他们希望何时清理它们。一个从来没有真正有动力的人至少有足够的动机被同行压力不加任何警告。

这使得团队氛围大大改善。在某些情况下,我们就什么是处理特定警告或一类警告的最佳方式进行了富有成效的讨论,这导致我们都成为更好的程序员,并且代码改进。我们都养成了关注更干净的代码的习惯,这样做的其他讨论 - 比如1000行递归函数是否具有良好的编码 - 非常容易。

队2:警告视为错误

队2几乎完全相同在beggining团队1。同样大的遗留代码充满了警告。同样数量的开发人员,积极主动,没有动力。在第二组中,尽管我们中的一个人(我)想留下警告作为警告,但集中精力减少警告。我的另一个有动机的同事声称所有其他开发人员都是一个漏洞,如果我们没有发出警告错误,他们将永远不会摆脱它们,并且您可以从不做这些事情获得什么样的好处?我在团队1中解释了我的经验,但他没有任何经验。

我仍然在团队中工作。这是一年后,我们的代码是免费的警告,但它充满了快速黑客摆脱警告和不必要的代码。虽然我们已经消除了许多实际问题,但许多潜在的问题已经席卷而来。

此外,团队凝聚力没有提高。如果有什么降级的话,管理层正在考虑打破团队出于这个原因。从不关心警告的同事们仍然没有,而且人们对质量的关注没有增加。事实上正好相反。每当有人谈论代码质量的时候,那些人就会翻阅他们的眼睛,并将其视为另一种压迫性的,愚蠢的管理痴迷,它只会降低生产力并且几乎没有好处。更糟糕的是,无论何时我们想要引入另一个可提供有用信息的警告,这是一个重大项目,因为我们要么必须更改我们的警告即错误政策,要么在引入警告之前修复所有现有警告。因为我们没有通过内在动机来观察和修复警告,所以前者很可能会导致真正的问题,所以我们将任务添加到积压之后,并且它会滞留和滞留。

另一个例子让我发现了这个问题,并写出了这个答案,它是C++ 11的[[弃用]]功能,我想用它来标记弃用的代码,以便逐步淘汰我们警告清理的一部分。然而,这与所有警告 - 错误不兼容。

我的建议:将警告视为团队心理上的错误,但不要告诉编译器这样做。也许把一些特别有害的警告视为错误,但要区别对待。

+3

“我仍然在第一队工作”你是说第二队? –