The effect of a goto statement in C++ on the stack
Asked Answered
E

3

5

When executing a goto statement in C++, are the two arrays in the code fragment below removed from the stack? Or will they be removed from the stack when the method returns?

retrySplit:
    ...
    uint32_t primsAbove[primitives.size()];
    uint32_t primsBelow[primitives.size()];
    ...
    goto retrySplit;

This question is not related to leaks resulting from using a goto statement, but concerned with the possibility of whether you can blow up your stack.

Eduard answered 8/11, 2014 at 14:27 Comment(3)
Conceptually they are removed when exiting the block (i.e. at closing brace } ...)Dressmaker
You should not care about the stack pointer. The location of these local variables will probably be reused after exiting the block.Dressmaker
It should be noted that, unless primitives.size() is a constant expression, this code is not standard, because it's using VLAs.Comportment
A
6

This program:

#include <iostream>

class X {
public:
 X() { std::cout << "ctor" << std::endl; }
 ~X() { std::cout << "dtor" << std::endl; }
};

int main(int argc, char** argv) {
 int i = 0;

label:
 X a;

 if (i == 0) {
  i = 1;
  goto label;
 }

 return 0;
}

Produces this output:

$ ./a.out 
ctor
dtor
ctor
dtor
Anhanhalt answered 8/11, 2014 at 14:35 Comment(0)
I
6

Yes, the arrays are destroyed. [stmt.jump]/2:

On exit from a scope (however accomplished), objects with automatic storage duration (3.7.3) that have been constructed in that scope are destroyed in the reverse order of their construction. […] Transfer out of a loop, out of a block, or back past an initialized variable with automatic storage duration involves the destruction of objects with automatic storage duration that are in scope at the point transferred from but not at the point transferred to.

You can also verify this through the following snippet:

#include <iostream>

struct A
{
    A() {std::cout << "A";}
    ~A() {std::cout << "D";}
};

int main()
{
    int counter = 0;

    label:
        if (counter++) // Exit on second run. 
            return 0;

        A a;
        goto label;
}

Demo. Your output should be AD. Note also that counter is not destroyed when jumping back to label.

Indestructible answered 8/11, 2014 at 14:30 Comment(0)
A
6

This program:

#include <iostream>

class X {
public:
 X() { std::cout << "ctor" << std::endl; }
 ~X() { std::cout << "dtor" << std::endl; }
};

int main(int argc, char** argv) {
 int i = 0;

label:
 X a;

 if (i == 0) {
  i = 1;
  goto label;
 }

 return 0;
}

Produces this output:

$ ./a.out 
ctor
dtor
ctor
dtor
Anhanhalt answered 8/11, 2014 at 14:35 Comment(0)
U
2

To be removed from the stack and to be alive are two different things. In your example the memory in the stack for arrays can be preserved however after the jump to the lable the arrays will be considered as not alive. That is before the jump destructors for elements of the arrays will be called and when the control achieve the definitions of the array when constructors of arrays' elements will be called.

Undressed answered 8/11, 2014 at 14:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.