在特定变量上禁用GCC的“可能未初始化使用”警告

37

我在一个堆栈变量上遇到了这个警告:

warning: object.member may be used uninitialized in this function
在这种情况下,我不希望强制初始化只为了消除警告,因为这会消耗CPU周期。该变量是一个POD结构,因此对其进行memset操作并非零成本。我可以验证该变量从未被未初始化使用,因此我只想在它上面抑制警告。
通常情况下,我确实想要这个警告,只是在这种特定的情况下不想要。如何抑制警告?
看起来pragma诊断是正确的方法,但需要相当新的GCC版本(4.6)。
未知是否有可接受的解决方案。

这个回答解决了你的问题吗?选择性地在翻译单元的一部分禁用GCC警告 - undefined
5个回答

34

试着这样做:

 #pragma GCC diagnostic ignored "-Wuninitialized"
        foo(b);         /* no diagnostic for this one */

这个编译器指示符有三种有趣和有益的方式:warningerrorignored。请参见6.56.10诊断指示符以了解它们的用法。该链接说:

GCC允许用户选择性地启用或禁用某些类型的诊断并更改诊断的类型。例如,项目策略可能要求所有源文件都使用-Werror进行编译,但某些文件可能具有特定类型警告的例外情况。或者,根据定义的预处理器宏,项目可以选择性地启用诊断并将其视为错误。


@awoodland:就算是我在2009年之前也没有看到过这个。似乎是在那之后才添加的。 - Nawaz
3
这也是我第一次遇到这个。它可能还需要几年时间才会在野外出现。多么有帮助的回答 :) - Tim Post
2
这是不允许在函数内使用的(GCC如是说)。 - edA-qa mort-ora-y
2
实际上这不是我想要的。这会禁用整个文件的警告,而不仅仅是特定的函数。 - edA-qa mort-ora-y
2
@edA-qa mort-ora-y:我认为,它是从GCC 4.6.0开始支持的。 - Nawaz
显示剩余6条评论

29

被接受的答案存在两个大问题,需要更多的评论。 首先,它会为整个文件停用警告。如果这个编译指示符位于头文件中,则可能用于其他目的。警告很有用,如果确实是误报,应该尽可能小地禁用警告。

然后OP中的警告是“可能未初始化”,可以通过-Wmaybe-uninitialized(相对于-Wuninitialized)来停用。

#pragma GCC diagnostic push                             // save the actual diag context
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"  // disable maybe warnings
function() or int variable;                             // impacted section of code
#pragma GCC diagnostic pop                              // restore previous diag context

6

GCC区分未初始化和自初始化,例如编译:

int main() {
   int i = i;
   return i;
}

使用gcc -Wall -Wextra不会产生警告,除非您明确添加了-Winit-self,但在我的快速测试中它被完全优化掉了。


这不会禁用我的警告,我也没有明确添加“-Winit-self”。 - edA-qa mort-ora-y
我不知道,我只是在代码中测试需要消除警告的部分,但它并没有消失。 - edA-qa mort-ora-y
gcc(4.4.1)对此没有抱怨,但g ++(相同版本)会出现问题! $ g ++ -Wall -Wextra selfinit.c /home/MICROSOL/agustinf/Work/x.c:在函数'int main()'中: /home/MICROSOL/agustinf/Work/x.c:2:警告:在此函数中未初始化'i' - gatopeich

6
@Nawaz已经按照要求回答了问题,但是您是否考虑过这样一个事实:您需要这个可能表明您在声明struct时太早或者嵌套层次不够恰当?通常情况下,最好在可以实际初始化它的地方声明struct,而不是在较早的时间声明并在各个位置进行填充。
此外,即使您现在可以验证它从未被未初始化使用,如果将来有其他人添加了新的代码路径,并且没有正确初始化,那么它会发生意想不到的错误。如果您禁用警告,它将静默编译并可能以意想不到的方式中断。除非您可以证明初始化占用了程序CPU的可测量量,否则最好直接进行初始化。

2
+1 始终编写代码,就好像下一个接触代码的人比你更笨一样。也许甚至是你自己,一年后你已经忘记了需要担心该值是否被初始化。也许如果他发布他的代码,我们可以帮助他找到一个相对高效的方法来消除警告。 - Karl Bielefeldt
1
您假设存在有效的默认初始化程序,但实际上并不存在。而且,是的,它需要可衡量的CPU时间。 - edA-qa mort-ora-y
4
如果没有有效的默认构造函数来创建这些对象之一,那么似乎更不应该在未初始化的情况下创建一个对象。您能否延迟构建直到您知道如何创建该对象? - Mark B
3
我不会反对这个观点,但我强烈反对为了初始化而无所顾虑地随意初始化。你可能会在这一点上把它初始化为任何东西(因为它最终会被覆盖掉),然后如果有人添加了实际上会使用这个“任何东西”的代码 - 你真的会受益吗?我认为你应该在第一次使用变量的地方立即抑制警告。使用#pragma GCC diagnostics push/pop可以避免警告在其他地方被抑制。 - Carlo Wood


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接