在C中的块范围内的变量声明之后使用goto

时间:2019-03-27 00:33:45

标签: c goto

我试图更好地理解C语言中的块作用域,以及该标准是否提供有关退出块作用域时弹出堆栈元素的任何保证,而这些保证可能在进入该作用域时已被推送到堆栈中。例如,在该块内声明了变量之后,跳转到块外的标签(就是,跳转到C中的标签,那里没有什么特别的东西)是否会导致堆栈损坏?

这是一个人为的示例,如果有助于进一步定义问题,请假设-O0。我的困惑是,当跳转到err2标签的执行路径被击中时,是否从堆栈中弹出fatal。因为标签在C中没有什么特别的,所以我假设err2不会从堆栈中弹出,并且会导致堆栈损坏。

void foo() 
{

    int err;
    if (err = baz()) {

        printf("error %i", err);
        int err2;
        if (err2 = another_thing())
            goto fatal;

    } 

    printf("done");
    return;

fatal:

    printf("there was a fatal error");

}

2 个答案:

答案 0 :(得分:4)

无法肯定地回答;但是大多数编译器会一次为该函数分配所有内存。

实际上,如果超出范围,访问指向它的指针是一个坏主意,否则您将不在乎。即使在-O0,范围外变量的内存也可能会被重用。

在任何情况下,局部变量都不会泄漏。堆栈不会变得不平衡。问题中的代码中没有任何危险。

答案 1 :(得分:1)

在使用GCC或MSVC的基于堆栈的处理器(如x86)的情况下,无论作用域如何,所有本地变量的堆栈空间都将在输入函数foo时保留。不论到达出口的方式如何,退出时都会释放堆栈框架,从而回收堆栈空间。

对于C ++,情况则有所不同。不是您的示例,但是如果您跳过构造函数,则该构造函数将不会运行,但是编译器仍将运行析构函数,这将导致混乱。幸运的是,正如Joshua在评论中指出的那样,现代编译器会检测到这种情况,并将生成编译时错误以避免这种情况。