Нужны ли атрибуты noreturn при выходе из функции?

c language-lawyer c11

167 просмотра

2 ответа

40758 Репутация автора

Являются ли noreturnатрибуты никогда не возвращаемых функций необходимыми, или это просто (возможно, преждевременно? - по крайней мере, для выходов, я не могу себе представить, зачем оптимизировать) оптимизацию?

Мне объяснили, что в контексте, таком как

void myexit(int s) _Noreturn {
   exit(s);
}
// ...
if (!p) { myexit(1); } 
f(*p);
/// ...

noreturnпредотвращает !pоптимизацию ветки. Но действительно ли допустимо, чтобы компилятор оптимизировал эту ветку? Я понимаю, что обоснование для его оптимизации было бы: «Неопределенное поведение не может произойти. Если p== NULL, разыменование это UB, поэтому pникогда не может быть NULLв этом контексте, поэтому !pветвь не запускается». Но не может ли компилятор решить проблему так же хорошо, предполагая, что это myexitможет быть функция, которая не возвращает (даже если она явно не помечена как таковая)?

Автор: PSkocik Источник Размещён: 18.07.2016 07:43

Ответы (2)


7 плюса

67636 Репутация автора

Решение

Это позволяет провести несколько оптимизаций. Во-первых, для самого вызова это может позволить упрощенную настройку, не все регистры должны быть сохранены, jmpвместо callили аналогично может использоваться инструкция . Затем код после вызова также можно оптимизировать, поскольку нет возврата к нормальному потоку.

Так что да, обычно _Noreturnэто ценная информация для компилятора.

Но как прямой ответ на ваш вопрос, нет, это свойство для оптимизации, поэтому в этом нет необходимости .

Автор: Jens Gustedt Размещён: 18.07.2016 07:50

2 плюса

7059 Репутация автора

Аксиома: стандарт - это определенный источник того, что четко определено в C.

  • Стандарт определяет assert, поэтому использование assertчетко определено.
  • assertусловно называют abort, _Noreturnфункция, поэтому , что позволило.
  • Каждое использование assertвнутри функции. Поэтому функции могут возвращаться или не возвращаться.
  • Стандарт имеет этот пример:

    _Noreturn void g (int i) { // causes undefined behavior if i <= 0
        if (i > 0) abort();
    }
    

    Поэтому функций условно возврата быть не должно _Noreturn. Это означает:

    • Для внешних функций компилятор должен предположить, что функция может не возвращаться и не может оптимизировать if-branch
    • Для «внутренних» определенных функций компилятор может проверить, действительно ли функция всегда возвращает результат, и оптимизировать ветвь.

В обоих случаях поведение скомпилированной программы согласуется с тем, что будет делать неоптимизирующая абстрактная машина C, и соблюдается правило «как будто».

Автор: a3f Размещён: 19.07.2016 04:42
Вопросы из категории :
32x32