На большом проекте я работаю, мы склонны использовать __builtin_expect ССАГПЗ в нашей проверки ошибок (обычно, когда эта ошибка будет прервать текущую операцию):НКУ: смешивание __builtin_expect и noreturn
if(__builtin_expect(failed, 0))
// handle error and fail
с другой стороны, мы имеем (небольшой) набор централизованных функций ошибок, которые имеют дело с определенными типами ошибок (то есть: у потребителя закончились данные).
Все эти функции заканчиваются выбросом исключения, поэтому они никогда не возвращаются.
Это оставляет проверку нашей ошибки, как:
if(__builtin_expect(got_bytes, 0))
customError(NoDataErrorCode, "No more data") ; // <-- always throws an exception
Чтобы избежать несколько предупреждений, которые я получаю здесь и там, я решил отметить те функции, как noreturn.
Прочитав документацию gcc для __builtin_expect и noreturn, я понимаю, что с этим не должно быть никаких проблем, но вы никогда не знаете.
Я написал небольшую тестовую программу:
#include <stdexcept>
void throwIt(void) __attribute__((noreturn)) ;
void throwIt(bool)
{
throw std::runtime_error("forced error") ;
}
void iffail(bool failed)
{
if(__builtin_expect(failed, 0))
throwIt(failed) ;
}
int main(int argc, char **)
{
iffail(!!(argc & 1)) ;
return 0 ;
}
компиляции с -O3 -S и проверкой коды сборки я узнал, что как и встроенный атрибут не имеет значение в данном конкретном случае. Удаление любых (или обоих) из них дает точно такой же код сборки. Это заставляет меня задаться вопросом, влияет ли __builtin_expect на простой оператор if с простым вызовом функции в нем.
ПРИМЕЧАНИЕ: аргумент bool throwIt заключается в том, чтобы заставить компилятор сделать что-то большее, чем просто вызвать функцию внутри if.
Так что мой вопрос: безопасно ли это соглашение или будет ли случай, когда это будет укусить.
Отказ от ответственности: Я не являюсь gcc-хакером. Я верю, что 'noreturn' сообщает компилятору, что функция не может вернуться. Это семантическое утверждение, которое может привести к неправильному коду, если неправильно использовать --- возврат из функции «noreturn» - это UB или что-то еще. (Я не уверен, что подсчет исключений считается возвратом для целей «noreturn», что кажется центральным для вашего вопроса. 'Longjmp' является' noreturn', хотя ...) '__builtin_expect' просто сообщает компилятору о вероятности ветвления; это не влияет на смысл программы. – tmyklebu
@tmyklebu В соответствии с собственной документацией gcc вы можете использовать функцию noreturn. –
Тогда ты золотой. – tmyklebu