为什么要禁用编译器警告?


26

这个答案和添加的注释显示了一种使用#pragma指令禁用多个编译器警告的方法。

为什么要这样做?通常,警告的存在是有原因的,我一直觉得它们是很好的理由。是否有应禁用警告的“有效情况”?现在我什么也想不出来,但也许就是我。


4
不知道为什么有人将其标记为关闭。对我来说似乎是一个非常合理的问题。+1

@Alastair Pitts:我建议迁移到程序员。后来我意识到自己的错误。
Tugrul Ates

3
警告信息是有原因的,是的,但也有一个原因,他们都没有错误消息。
所罗门慢速

2
@jameslarge您的评论很好地总结了这种情况。警告是编译器告诉您某种情况似乎错误的,这暗示可能是正确的。如果肯定是错误的,那将是一个错误。由于某些警告可能是误报,因此应始终存在一种编写代码的方式,以消除警告。不幸的是,有时最务实的方式是通过实用程序。由此得名。
埃里克·利珀特

它不是禁用,而是隐藏。问题仍然存在,只是您不会按原样看到它
Sisir

Answers:


11

我只有一种情况禁用了警告。我考虑了警告错误,因此通常不会发布警告。但是,在为客户开发API时,我遇到了一个问题,即一个应用程序在迁移阶段需要一种方法,而该库中不应包含任何其他方法。

我可以告诉所有API用户他们不应调用此方法的最好方法是将其标记为过时。但是,这意味着一个有效的用例被标记为编译警告。

埃里克·利珀特(Eric Lippert)写了几篇有关警告的文章,您可以在其中找到有关编译器团队对警告的看法的信息。

内部类型的内部字段

未使用的using指令未标记警告


10

以下是一些警告,在这些警告中,文档提供了您可能要禁用它们的原因:

其他示例包括警告,如果您知道仍要使用旧方法或使用从未在本地读取但使用反射的私有成员,则使用折旧方法。

以我的经验,C#与其他语言(例如C ++)相比,禁用警告的需求更少。正如艾里克·利珀特(Eric Lippert)在他的博客中所说,这主要是因为“他们只在我们几乎可以肯定地说代码被破坏,误导或无用的情况下才保留警告”。


3
真好 我认为第一个是最清晰的,因为它提供了一个非常具体的案例一个辩解(例如,第三个显示了一些代码,这些代码永远不会通过我的团队审查)。 这个问题讨论过时/过时的警告。基本上,遗留代码中仍然需要它们,但是您不希望使用它们来阻止任何新代码。旧代码应禁止显示警告。
格雷格·杰克逊

我已经在Excel中完成了很多宏编程,由于各种原因(例如自动保存,自动退出,通知等),我不得不禁用警告。当然,您可能对这些警告不感兴趣...
Dave Mess

@ICR我根本不记得在Java中禁用编译器警告。我要做的就是避免使用不推荐使用的方法。
Mahmoud Hossam

@Mahmoud我经常发现自己在使用泛型进行非常复杂的操作时都不得不抑制“未经检查”的警告。但是在荒谬的警告方面将Java与C ++混为一谈可能不公平-编辑了我的答案。
ICR

@ICR Java强制使用泛型来提供集合中的类型安全性,尽管有些人将其视为约束,但我认为它是一个功能,它使编写代码有些痛苦,但可以节省生命,是的,C ++编译器输出当涉及到STL或带有模板的内容时,这有点令人恐惧。
Mahmoud Hossam

8

我经常遇到C语言中的一个例子:

int doSomething(int argument1)
{
#ifdef HARDWARE_TYPE_A
    performAction(argument1);
#else
    displayNotSupportedMessage();
#endif
}

该参数仅在某些平台上相关,而在不相关的平台上,我的编译器会抱怨,并且由于我将警告转换为错误,因此它将阻止其构建。

将警告转换为错误几乎需要对“不是这个,我比在这种情况下的编译器知道的更多”进行转义。


6

许多必不可少的Java库从未更新过,以消除对不安全类型转换的需求。抑制这些警告是必要的,以便其他更重要的警告将被注意到并得到纠正。


5

我从事嵌入式工作,我似乎记得一个或两个禁用警告的时间,因为我所做的事情对编译器而言似乎毫无用处,但实际上在硬件中产生了真实的影响。

唯一的其他时间是当我在使用一些数据结构的不同思想(例如,如何表示字节数组-char或unsigned char?)的代码库上工作时。在这些情况下,我可能会禁用警告,因为另一种选择是花几天时间遍历代码并修改一部分,或进行数百次强制转换。


3

有很多理由有选择地禁用编译器警告,即使对于争取最佳实践的项目也是如此。

  • 不同的编译器(或相同编译器的不同版本)
    编译器以微妙的不同方式处理警告。给出不会影响其他编译器的错误肯定警告。在这种情况下,对那些编译器禁用警告可能是有意义的,而不是编辑有效的代码以使只会影响某些编译器的假阳性警告安静下来,尤其是对于最终最终将不受支持的较旧的编译器。
  • 使用生成的代码:
    可以安全地忽略一些与代码卫生有关的警告(死代码,条件语句的主体重复,超过类型限制的比较),因为它们是无害的,编译器将对其进行优化。
    当然,生成不会引发这些无害警告的代码也是一种选择,但是可能会比其价值更大。
  • 外部代码警告:
    也许您使用了项目中包含的众所周知的qsort或md5校验和实现。该代码已被许多项目使用,并且运行良好,但是可能有些挑剔的警告通常会针对您自己的代码进行纠正。
    但是,对于外部代码,仅禁用警告可能会比较省事(假设警告绝对无害的)。
  • 由系统标题引起的警告:
    即使例如GCC / Clang支持-isystem,在某些情况下,系统标题中的差异也会导致可以忽略的警告(也许一个函数在一个系统上具有带符号的返回值,但在另一个系统上没有返回值),从而触发-Wsign-compare警告。
    另一种情况是在系统头文件中定义了宏,您可以将宏复制粘贴到您自己的代码中以对其进行修改,但是所有事情都被认为是更好的,而不必担心维护来自第三方库的宏...因此它更好使警告静音(也许宏错过了引起-Wsign-conversion例如的强制转换)。
  • 存根代码中未使用的警告:
    您可能会警告未使用的参数,但是,在仅包含存根函数的单个文件中存出整个库时,这将不会强加于(void)arg1; (void)arg2; (void)arg3; ...每个存根函数的主体中。在这种情况下
    最好压制-Wunused-parameter一下。

请注意,在所有这些例子中,它假定的禁止警告不会隐藏真正的bug,如:-Wredundant-decls-Wunused-parameter-Wdouble-promotion,也许-Wpedantic......,你知道你在做什么!


2

是否有效,有时会绕过构建服务器上的“将警告作为错误处理”指令。

除此之外,我也没有想到。禁用警告通常表示“丑陋的骗局”。


2

上一次我们禁用某些警告是因为实习生给我们留下了不好的代码。我已经有了更好的工作,明确的转换边界取代了随意的数据表示形式。

同时,我们需要对其进行编译,并且希望启用“警告是错误”选项,因此我们取消了一些警告。


2

目前,我唯一忽略的警告是

  warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)  

因为微软没有实现C ++规范(文档甚至说它们没有实现),并且不允许函数声明特定的throws,所以所有函数只能抛出throw()或throw(...),即什么也没有。

从HelpViewer 1.1:

 A function is declared using exception specification, which Visual C++ accepts but does not implement. Code with exception specifications that are ignored during compilation may need to be recompiled and linked to be reused in future versions supporting exception specifications. 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.