не удалось, но сделал не минимальный, в котором воспроизводится "плохое поведение" программы. Там, в частности, происходит виртуальный вызов метода и в этот момент происходит SF. Сборка проекта при этом должна происходить с флагами -fdevirtualize и -finline-small-functions. В противном случае все работает правильно.
Сегодня наткнулся на статью. Там говорится, что нужно избегать слова final, так это может привести к тому, что компилятор ошибется при оптимизации. А у меня тот самый виртуальный метод был как раз помечен как final. Я убрал его и программа отработала правильно 😳.
Кто-то сталкивался с подобным? Можете прокомментировать?
> Там говорится, что нужно избегать слова final, так это может привести к тому, что компилятор ошибется при оптимизации Где конкретно это написано? Не смог найти
Ну либо компилятор конкретно ваш плохой, либо внутри виртуальной функции меняется динамический тип объекта, либо его втейбл
звучит скорее как баг в компиляторе
Сорри за введение в заблуждение. Действительно, такого там нет. Но тем не менее, не использование final, на первый взгляд, решило проблему...
Внутри виртуальной функции просто std::cout
ну без кода непонятно
Наличие final позволяет сделать чуть больше оптимизаций. Если оптимизации приводят к крашу, значит либо в коде UB (по везению не воспроизводится без оптимизаций), либо баг в компиляторе
MRE, к сожалению, подготовить не удалось пока.
А уж не из конструктора/деструктора ли вызов делается?
А вызов делается через объект final или derived класса? Судя по флагам именно этот вызов должен быть заинлайнен чтобы поломалось. Может оно как то не кастует указатель из derived при инлайне, надо disasm смотреть
Вызов виртуального метода делается из базы, этот метод переопределен в наследнике, где он помечен как final.
И метод, вызывающий метод, вызывается не из конструктора базы? Просто уточняю, что запрещено вызывать из конструктора не только напрямую, но и с какими-то промежуточными вызовами
Ну если точно через базу, можно просто смотреть сгенерированный код в месте вызова с final и без, он должен быть идентичен.
Нет. Создаётся объект на стеке. После этого у него вызывается метод.
Ага, то есть фактически компилятор знает тип и этот вызов может таки быть девиртуализирован.
Обсуждают сегодня