Выполнение "UB-кода" из-за неправильного предсказания ветвления
Есть код типа такого:
if (ptr) ptr->do_something();
Из-за неудачного branch prediction CPU начал выполнять ptr->do_something(); с нулевым указателем. Что происходит в таком случае? segfault неявно подавляется? Является ли код, где UB возникает только в случае перестановки операций, UB в целом?
Ответы (3 шт):
Если код написан правильно, то ничего не случится. Могу ошибаться, но вроде бы превентивное исполнение вообще не затрагивает код с побочными эффектами.
А вот если неправильно, то есть минимум один случай, в котором превентивное исполнение может привести в сбою. Это использование типа void-функции в качестве коллбэка, который на самом деле должен возвращать int - даже если возвращаемое значение нигде не используется.
UB никогда не возникает в результате каких-то нелинейных манипуляций процессора в ходе выполнения кода. UB может содержаться исключительно в исходном коде программы. Если исходный код написан так, что в нем не возникает никакого неопределенного поведения при выполнении на референсной абстрактной машине, то его не должно будет возникать и при исполнении на реальной машине. Собственно в выражении "Неопределенное поведение" идет речь о поведении абстрактной машины, не определенном в стандарте. Задача компилятора заключается в том, чтобы побочные эффекты от выполнения на реальной машине соответствовали таковым при исполнении на абстрактной. А если какие-то неполадки при исполнении программы, не содержащей неопределенного поведения, и случаются, то это будет уже из-за проблем в компиляторе, который не корректно сгенерировал машинный код, или в самом вычислительном устройстве.
"Неудачное" ветвление основано на простом правиле, при первом ветвлении, когда в предсказатели нет никакой информации о том какое ветвление наиболее вероятно, он всегда выбирает то которое ведет к коду с наименьшим адресом. Поскольку процедуру do_something() ты написал "выше" чем условие if (ptr) то branch prediction решил сразу перейти к ней еще до того как условие было проверено, если ты перенесешь ее "ниже" по коду, то тогда branch prediction при первом проходе будет считать что условие не выполняется, в последующих проходах он будет руководствоваться уже накопленной статистической информацией.
UB возникает только в случае перестановки операций, UB в целом?
Нет, после того как будет выяснено что это невалидная ветвь, ситуация будет аннулирована.