Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is jumping over a variable initialization ill-formed or does it cause undefined behaviour?

Consider this code:

void foo()
{
    goto bar;
    int x = 0;
    bar: ;
}

GCC and Clang reject it, because the jump to bar: bypasses variable initialization. MSVC doesn't complain at all (except using x after bar: causes a warning).

We can do a similar thing with a switch:

void foo()
{
    switch (0)
    {
        int x = 0;
        case 0: ;
    }
}

Now all three compilers emit errors.

Are those snippets ill-formed? Or do they cause UB?

I used to think that both were ill-formed, but I can't find the revelant parts of the standard. [stmt.goto] doesn't say anything about this, and neither does [stmt.select].

like image 752
HolyBlackCat Avatar asked Jan 27 '20 12:01

HolyBlackCat


People also ask

What causes undefined behavior C++?

So, in C/C++ programming, undefined behavior means when the program fails to compile, or it may execute incorrectly, either crashes or generates incorrect results, or when it may fortuitously do exactly what the programmer intended.

What is the initialization of a variable?

Initialization is the process of assigning a value to the Variable. Every programming language has its own method of initializing the variable. If the value is not assigned to the Variable, then the process is only called a Declaration.

Which is not variable initialization?

Uninitialized means the object has not been given a known value (through any means, including assignment). Therefore, an object that is not initialized but is then assigned a value is no longer uninitialized (because it has been given a known value).

Why variable initialization is important?

This refers to the process wherein a variable is assigned an initial value before it is used in the program. Without initialization, a variable would have an unknown value, which can lead to unpredictable outputs when used in computations or other operations.


1 Answers

It's ill-formed when the initialization is non-vacuous.

[stmt.dcl]

3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization (including ones in conditions and init-statements). A program that jumps 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 vacuous initialization ([basic.life]). In such a case, the variables with vacuous initialization are constructed in the order of their declaration.

The initializer makes the initialization non-vacuous. To contrast, this

void foo()
{
    goto bar;
    int x; // no initializer
    bar: ;
}

would be well-formed. Though the usual caveats about using x with an indeterminate value would apply.

like image 61
StoryTeller - Unslander Monica Avatar answered Oct 09 '22 19:10

StoryTeller - Unslander Monica