Segmentation fault when jumping to goto over VLA array

血红的双手。 提交于 2021-01-27 06:39:40

问题


The following example demonstrates the issue:

#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;
        }
}

Initially, the initialization of "remaining" variable was a bit long and I used goto to initialize it on one line. However, now this example gives segmentation fault on the printf line.

It looks like the array is not initialized properly.

Even gdb cannot print the tmp array's address:

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>

My gcc version:

gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

compiling with:

g++ -o testc test.cpp

If I remove the goto, or replace the variadic array with a fixed array, the segmentation fault is gone. What is happening actually?

Is this a gcc bug? If the combination of goto and variadic arrays is not allowed, there should be a warning?


回答1:


Variable length arrays(VLA) are a C99 feature that gcc supports as an extension in C++ and in C99 a jump across a VLA declaration is undefined behavior, from the draft C99 standard section 6.8.6.1 The goto statement:

A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier.

clang and gcc 4.9 actually makes this an error and says:

error: goto into protected scope
    goto loop;
    ^

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

See the gcc bug report: Jumps into VLA or VM scope not rejected for C++.

The rules for jumping past a declaration of an automatic variable in C++ is covered in section 6.7 [stmt.dcl] which says:

It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps87 from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer (8.5). [ Example:

void f() {
    // ...
    goto lx; // ill-formed: jump into scope of a
ly:
    X a = 1;
    // ...
lx:
    goto ly; // OK, jump implies destructor
             // call for a followed by construction
            // again immediately following label ly
}

—end example ]



来源:https://stackoverflow.com/questions/29124145/segmentation-fault-when-jumping-to-goto-over-vla-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!