在特定变量上禁用 GCC“可能未初始化”
Posted
技术标签:
【中文标题】在特定变量上禁用 GCC“可能未初始化”【英文标题】:Disable GCC "may be used uninitialized" on a particular variable 【发布时间】:2011-02-22 16:23:38 【问题描述】:我在堆栈变量上收到此警告:
warning: object.member may be used uninitialized in this function
在这种情况下,我不希望强制初始化只是为了消除警告,因为它会消耗 CPU 周期。该变量是一个 POD 结构,因此其上的 memset
不是零成本。我可以验证该变量从未在未初始化的情况下使用过,所以我只想取消它的警告。
一般来说,我确实想要警告,只是在这个特定场景中不针对这个特定变量。如何抑制警告?
看起来编译指示诊断是正确的方法,但它们需要最新版本的 GCC (4.6)
在该版本已知之前没有可接受的解决方案。
【问题讨论】:
【参考方案1】:尝试这样做:
#pragma GCC diagnostic ignored "-Wuninitialized"
foo(b); /* no diagnostic for this one */
此编译指示包含三种有趣且有用的风格:warning
、error
、ignored
。有关它们的用法,请参阅6.56.10 Diagnostic Pragmas。链接说,
GCC 允许用户有选择地 启用或禁用某些类型的 诊断,并改变类型 诊断。 例如,一个 项目的政策可能要求 所有源代码都使用 -Werror 编译,但 某些文件可能有例外 允许特定类型的警告。 或者,项目可能会选择性地启用 诊断并将其视为错误 取决于哪些预处理器宏 已定义。
【讨论】:
@awoodland:我在 2009 年之前都没有看到这个。看起来它是在那之后添加的。 我也是第一次遇到。在野外看到它可能还需要几年的时间。多么有用的答案:) 不允许在函数内部使用(GCC 这么说)。 其实这不是我想要的。这会禁用整个文件的警告,而不仅仅是特定功能。 @edA-qa mort-ora-y:我想。 GCC 4.6.0 支持它【参考方案2】:接受的答案有两个大问题,需要的不仅仅是评论。 首先,它会停用整个文件的警告。如果该编译指示位于标头中,则可能更多。警告很有用,如果它确实是误报,则应该为一堆尽可能小的代码禁用警告。
那么 OP 中的警告是“可能未初始化”,它被 -Wmaybe-uninitialized 停用,而不是 -Wuninitialized。
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
function() or int variable;
#pragma GCC diagnostic pop
【讨论】:
【参考方案3】:@Nawaz 已按照具体要求回答了该问题,但您是否考虑过您需要此信息这一事实可能表明您声明 struct
太早/嵌套范围不合适?如果您可以在可以实际初始化它的位置声明struct
,而不是提前声明它并将其填充到不同的位置,通常会更受欢迎。
此外,即使您现在可以验证它从未使用过未初始化,但如果其他人将来添加了新的代码路径并且它没有正确初始化怎么办?如果您禁用警告,那么它将静默编译并且可能以意想不到的方式中断。除非您可以证明初始化占用了您程序的大量 CPU,否则最好先进行初始化。
【讨论】:
+1 始终编写代码,就好像下一个接触代码的人比你自己笨一样。甚至可能是一年后您不记得您需要担心该值被初始化。也许如果他发布他的代码,我们可以帮助他找到一种相对有效的方法来消除警告。 您假设有一个有效的默认初始化程序,但实际上没有。是的,它需要大量的 CPU 时间。 @edA-qa mort-ora-y 如果无法有效地默认构造这些对象之一,那听起来更像是您根本不应该创建一个未初始化的对象。您是否可以延迟构建,直到您知道如何创建对象? 我不会对此投反对票 ;),但我强烈不同意当您不知道将其初始化为什么时应该初始化某些东西的观点,只是为了初始化。此时您可能会将其初始化为 ANYTHING(无论如何它都会被覆盖),然后如果有人添加实际上开始使用此 ANYTHING 的代码 - 您真的会更好吗?您应该在第一次使用变量的地方取消警告。使用#pragma GCC diagnostics push/pop
以避免警告在其他地方也被抑制。【参考方案4】:
GCC 区分未初始化和自初始化,例如编译:
int main()
int i = i;
return i;
gcc -Wall -Wextra
不会给出任何警告,除非您也明确添加了 -Winit-self
,但经过我的快速测试,它已完全优化。
【讨论】:
这不会禁用我的警告,我也没有明确添加-Winit-self
。
我不知道,我只是在需要摆脱警告的代码中进行测试,但没有。
gcc (4.4.1) 没有抱怨这一点,但 g++ (相同版本)会! $ g++ -Wall -Wextra selfinit.c /home/MICROSOL/agustinf/Work/x.c: In function 'int main()': /home/MICROSOL/agustinf/Work/x.c:2: warning: 'i' is used uninitialized in this function
【参考方案5】:
Selectively disable GCC warnings for only part of a translation unit?
【讨论】:
以上是关于在特定变量上禁用 GCC“可能未初始化”的主要内容,如果未能解决你的问题,请参考以下文章
如何避免 MSVC 警告 C4701:可能未初始化的局部变量
VS编译报错:error C4703: 使用了可能未初始化的本地指针变量“xxx”