【问题标题】:The effect of a goto statement in C++ on the stackC++ 中 goto 语句对堆栈的影响
【发布时间】:2015-01-05 05:45:48
【问题描述】:

在 C++ 中执行goto 语句时,下面代码片段中的两个数组是否从堆栈中移除?或者当方法返回时它们会从堆栈中移除?

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

这个问题与使用 goto 语句导致的泄漏无关,而是与您是否会炸毁堆栈的可能性有关。

【问题讨论】:

  • 从概念上讲,它们在退出块时会被删除(即在右括号} ...)
  • 你不应该关心堆栈指针。这些局部变量的位置可能会在退出块后被重用。
  • 需要注意的是,除非primitives.size()是一个常量表达式,否则这段代码是不标准的,因为它使用了VLA。

标签: c++ stack-overflow goto destroy callstack


【解决方案1】:

这个程序:

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

产生这个输出:

$ ./a.out 
ctor
dtor
ctor
dtor

【讨论】:

    【解决方案2】:

    是的,数组被销毁了。 [stmt.jump]/2:

    从范围退出时(无论如何完成),具有自动 在该范围内构建的存储期限(3.7.3)是 以它们建造的相反顺序被摧毁。 […] 转出 循环,块外,或返回初始化变量 自动存储持续时间涉及销毁对象 在转移点范围内的自动存储持续时间 从但不是转移到的点。

    你也可以通过下面的sn-p来验证:

    #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。你的输出应该是AD。 另请注意,counter 在跳回label 时不会被破坏。

    【讨论】:

      【解决方案3】:

      从堆栈中移除和活着是两件不同的事情。在您的示例中,可以保留数组堆栈中的内存,但是在跳转到标签后,数组将被视为无效。即在数组元素的跳转析构函数被调用之前,当控件实现数组的定义时,数组元素的构造函数将被调用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2012-05-10
        • 2014-11-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多