当我编译下面的C ++程序时,我需要添加-O2
标志以获取有关未初始化变量的警告。为什么会这样?
unsigned long fac(unsigned long n)
{
unsigned long product;
while (n > 1)
{
product = product * n;
n = n - 1;
}
return product;
}
➜ a g++ --version
g++ (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
编辑:为澄清这个问题,我当然启用了警告。
答案 0 :(得分:4)
警告在-O2(或任何其他优化)模式下显示,并且选项-Wmaybe-uninitialized
处于打开状态。 -Wmaybe-uninitialized
和-Wall
以及启用的任何优化模式都将打开。
根据GCC documentation这样做的原因是:
-Wmaybe-uninitialized
对于自动(即本地)变量,如果存在该函数的路径 使用已初始化的变量的条目,但是还存在其他一些变量 变量未初始化的路径,编译器将在以下情况下发出警告 它不能证明未初始化的路径在运行时未执行。 这些警告仅在优化编译中可用,因为否则 GCC不会跟踪变量的状态。这些警告是可选的,因为GCC可能无法确定 即使出现错误,代码仍然正确。
然后以一个示例说明上述情况如何发生。
答案 1 :(得分:1)
要更深入地回答为什么问题,这样做主要是为了减少误报率和编译时间。产生这些警告(-Wmaybe-uninitialized
风格)的过程在编译管道中运行得很晚(请参阅gcc/passes.def
;相应的pass_late_warn_uninitialized
过程在第338行左右)。 GCC尽力为该警告生成尽可能少的误报。为此,它需要有关程序的更精确的信息。为了获得此信息,它需要事先进行一些分析/转换(例如,jump threading特别有益)。而且其中有些过于昂贵,无法在-O0
上启用。
GCC开发是公开进行的。通常在邮件列表和bugzilla中讨论所有主要决策。例如,请参见this comment。
答案 2 :(得分:-1)
未初始化的变量不是技术错误; x86 / x64程序集中的内存可以未初始化。从未初始化的内存中读取(受保护/长模式限制可以读取)是有效的。您将获得未定义的值,但在技术上有效。
显示给您的内容取决于编译器(因此,它是可用的选项)。较高级别的选项可能会将其视为错误并停止;但是从技术上讲,这是可能的。