Использование goto после объявления переменной в области видимости блока C - PullRequest
2 голосов
/ 27 марта 2019

Я пытаюсь лучше понять область видимости блока в 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 ]

4 голосов
/ 27 марта 2019

Невозможно ответить наверняка;однако большинство компиляторов выделяют всю память для функции сразу.

На практике, если он выходит из области видимости, доступ к указателю на него является плохой идеей, в противном случае вам все равно.Даже при -O0 память для переменной, находящейся вне области видимости, может быть повторно использована.

Ни в коем случае не будет утечка локальных переменных.Стек не станет несбалансированным.В коде вопроса нет ничего опасного.

1 голос
/ 27 марта 2019

В случае процессора на основе стека, такого как x86, использующего GCC или MSVC, пространство стека для всех локальных компьютеров независимо от области будет зарезервировано при входе в функцию foo. Кадр стека будет развернут при выходе, освободив пространство стека, как и ожидалось, независимо от того, как был достигнут выход.

Однако для C ++ ситуация иная. Не совсем ваш пример, но если вы перепрыгнете через конструктор, то конструктор не запустится, однако компилятор все равно запустит деструктор, что приведет к путанице. К счастью, как отметил Джошуа в комментариях, современные компиляторы обнаруживают эту ситуацию и генерируют ошибку времени компиляции, чтобы избежать этой ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...