在C++中过度"交叉变量初始化"错误?

per*_*ror 8 c++ g++ clang++

我注意到g++有点过于严格的抱怨crossed initialization,我想知道为什么这些误报错误只能通过在编译时查看程序的SSA形式来消除.

让我举一个非常简单的例子:

#include <cstdlib>

int main ()
{
  goto end;

  int i = 0; // unused variable declaration

 end:
  return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

使用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]
Run Code Online (Sandbox Code Playgroud)

因此,它会引发一个实际没有风险的错误,因为该变量未被使用(编译器显然同时具有这两个信息,并且不能将它组合起来推断错误是误报).

更奇怪的是,我希望LLVM在分析程序方面更有效率.所以,我尝试clang++(LLVM)这个简单的例子clang++ -Wall -Wextra -o example1 example1.cc(clang++3.4).而且,我得到了相同的错误消息:

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.
Run Code Online (Sandbox Code Playgroud)

所以,我很确定我在这里遗漏了一些重要的东西,这个问题使得这种假阳性的检测比我更难.但是,我不知道它是什么.或许,C++规范明确指出它必须是这样的.

如果有人有想法,请随时分享!

编辑:我也在C(gccclang)中编译完全相同的代码,并且只是关于i成为未使用的变量的警告它很好.因此,它强调了这一事实,即更可能与C++规范相关联,而不是在编译时检测此问题的问题.

Wal*_*ter 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;
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*son 8

这是不允许的,因为您可能会为未正确构造的对象调用析构函数.不可否认,int没有构造函数或析构函数,但它使所有类型的对象都"公平".从技术上讲,标签上的某些东西end:可能正在使用i,并且通过严格规则,它可以防止机器必须检查每一个代码路径(这成为"暂停问题").