跳转到VLA阵列时出现分段错误

时间:2015-03-18 14:01:50

标签: c++ gcc variable-length-array

以下示例演示了此问题:

#include <cstdio>

int main()
{
        unsigned int remaining=1;

        goto loop;

        while(remaining) {
                unsigned char tmp[remaining];
                printf("&tmp: %p\n",tmp);
loop:
                remaining = 512;//or something else;
        }
}

最初,“剩余”变量的初始化有点长,我使用goto在一行上初始化它。但是,现在这个例子给出了printf行的分段错误。

看起来数组没有正确初始化。

即使gdb也无法打印tmp数组的地址:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005b8 in main () at test.cpp:11
11          printf("&tmp: %p\n",tmp);
(gdb) p tmp
$1 = 0xfffffffffffffe00 <error: Cannot access memory at address 0xfffffffffffffe00>

我的gcc版本:

gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

编译:

g++ -o testc test.cpp

如果我删除goto,或用固定数组替换可变参数数组,则分段错误消失。 实际上发生了什么?

这是一个gcc bug吗?如果不允许goto和可变参数数组的组合,那么应该有警告吗?

1 个答案:

答案 0 :(得分:5)

可变长度数组( VLA )是gcc支持的C99特性an extension in C++,在C99中,跳过VLA声明是未定义的行为,来自草案C99标准部分{{ 1}} goto语句

  

goto语句不得从具有标识符的范围之外跳转   在该标识符范围内的可变修改类型。

6.8.6.1clang实际上是一个错误,并说:

gcc 4.9

请参阅gcc bug report: Jumps into VLA or VM scope not rejected for C++

在{+ 1}} [stmt.dcl] 部分中介绍了跳过C ++中自动变量声明的规则:

  

可以转移到块中,但不能转移到块中   通过初始化绕过声明。一个跳过87的程序   具有自动存储持续时间的变量不在的点   范围到它在范围内的地方是不正确的,除非   变量具有标量类型,具有普通默认值的类类型   构造函数和一个简单的析构函数,一个cv限定版本   声明这些类型或前面类型之一的数组   没有初始化程序(8.5)。 [例如:

error: goto into protected scope
    goto loop;
    ^

note: jump bypasses initialization of variable length array
            unsigned char tmp[remaining];
                          ^
     

-end example]

相关问题