我注意到g++
对crossed initialization
抱怨过于严格,我想知道为什么在编译时只是通过查看程序的SSA形式就无法消除这些误报错误。
让我举一个非常简单的例子:
#include <cstdlib>
int main ()
{
goto end;
int i = 0; // unused variable declaration
end:
return EXIT_SUCCESS;
}
使用g++ -Wall -Wextra -o example1 example1.cc
(g++
4.8.1)编译时,编译器会显示以下错误消息:
example1.cc: In function ‘int main()’:
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive]
end:
^
example1.cc:6:8: error: from here [-fpermissive]
goto end;
^
example1.cc:8:7: error: crosses initialization of ‘int i’
int i = 0;
^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable]
因此,它会引发一个实际上没有风险的错误,因为该变量未被使用(编译器显然同时具有这两个信息,并且无法将其组合以推断错误是误报)。
更奇怪的是,我希望LLVM在分析程序方面更有效率。所以,我使用clang++
(clang++ -Wall -Wextra -o example1 example1.cc
3.4)对这个简单示例尝试了clang++
(LLVM)。而且,我得到了同样的错误信息:
example1.cc:8:7: warning: unused variable 'i' [-Wunused-variable]
int i = 0;
^
example1.cc:6:3: error: goto into protected scope
goto end;
^
example1.cc:8:7: note: jump bypasses variable initialization
int i = 0;
^
1 warning and 1 error generated.
所以,我很确定我在这里遗漏了一些重要的东西,这个问题使得这种假阳性的检测比我更难。但是,我不知道它是什么。或许,C ++规范明确指出它必须是这样的。
如果有人有想法,请随时分享!
编辑:我还在C(gcc
或clang
)中编译了完全相同的代码,只是在i
被警告时它正常未使用的变量。因此,它强调了这一事实,即更可能与C ++的规范相关联,而不是在编译时检测到此问题的问题。
答案 0 :(得分:10)
编译器没有任何问题。根据标准,您的代码格式不正确。
在您的特定情况下,可能不需要标准的要求,并且可以允许跳转并且编译器可以创建有效的代码。但是,这只是因为变量int i
的初始化没有副作用。
只需将跳跃的部分包含在自己的范围内,即可使代码有效:
#include <cstdlib>
int main ()
{
goto end;
{
int i = 0; // unused variable declaration
}
end:
// cannot use i here, as it's not defined.
return EXIT_SUCCESS;
}
答案 1 :(得分:8)
这是不允许的,因为可能会为未正确构造的对象调用析构函数。不可否认,int
没有构造函数或析构函数,但它使所有类型的对象都“公平”。从技术上讲,标签end:
上的某些东西可能正在使用i
,并且通过使规则严格,它可以防止机器必须检查每个代码路径(这成为“暂停问题”)。