В прошлом году (уже прошел почти целый год) мы наконец перешли на новую версию Boost-1.65.1, и под капотом вы обнаружите три ошибки буста, с которыми мы столкнулись.
Также важно отметить, что до этого мы использовали в нашем ПО boost -1.62.1, так как некоторые ошибки появлялись в boost раньше версии 1.65.1. В нашем проекте есть специальная команда интеграции, основной задачей которой является миграция всего ПО на новую версию библиотек, Visual Studio, новые версии низкоуровневых компонентов (базовые, от которых зависит большинство остальных компонентов) и т.д. также отвечает за устранение всех возникающих проблем, естественно с помощью сопровождающих компонентов, если это необходимо.
Итак, ошибки, которые мне особенно запомнились.
Ошибка в boost::filesystem
Этот баг появился довольно быстро.Тесты начали проваливаться с ошибкой «Нарушение прав доступа» при поиске полного пути к заданному имени файла.
Функция вызвала boost::filesystem::exist, и программа аварийно завершилась.
После запуска еще нескольких тестов было замечено еще несколько подобных случаев, и во всех случаях вызов boost::filesystem::exist производился над глобальными переменными.
Судя по всему, что-то изменилось за время существования буст-переменных.
Билет на обнаруженную ошибку очень легко отправить в Google. сообщение об ошибке в boost::filesystem::exist Оказалось, что этот баг появился в бусте начиная с версии 1.64. На самом деле проблема была в вызове make_permissions (используемом в filesystem::exist).
В версии 1.64 реализация make_permissions была изменена для использования глобальных переменных, а это означает, что при попытке вызова filesystem::exist для инициализации глобальной переменной или объекта глобальные переменные, используемые в make_permissions, возможно, еще не были инициализированы.
Таким образом, попытка доступа к несозданной переменной вызывает исключение.
Обходной путь Тесты, в которых глобальные переменные использовались только один раз, были перенесены в соответствующие тесты и стали локальными переменными.
Даже не спрашивайте, почему этого не сделали раньше, я не мейнтейнер этого кода.
В других случаях мы использовали одиночки .
Ошибка в boost::python
В тестах с использованием boost::python была обнаружена странная вещь.При тривиальном вызове eval() для литерала (например, «40+2») все в порядке.
А если мы определим переменные, а затем используем их в выражениях, мы получим сообщение о том, что в вычислениях используются неопределенные переменные (ОШИБКА: [имя] не определено).
Я уже потратил больше времени на решение этой проблемы.
Я не смог найти заявку на эту проблему в трекере ошибок boost, поэтому мне пришлось обратиться за помощью к команде этого компонента.
Информация об ошибке была быстро найдена на GitHub .
Так получилось, что глобальные и локальные объекты не использовались в реализации eval. Желая Удачи в поисках исправления без перекомпиляции исходного кода команда раскланялась :) Обходной путь Но потом я вспомнил примечания к выпуску boost-1.65.1 и определенно было что-то для boost::python. Ура, выход есть! Баг был допущен при добавлении новой реализации eval с поддержкой аргументов char const*, которая теперь вызывается в старой реализации eval со строковым аргументом (Особо внимательные люди могли заметить вызов этой функции в коде из ссылка на гитхаб).
И новая функция работает так, как и ожидалось.
повышение::numpy
Это моя наименее любимая часть.boost::python::numeric был удален, и теперь в качестве альтернативы доступен boost::python::numpy. Но код, использовавший числовые значения, пришлось существенно переработать, поскольку речь шла не только о переименовании пространств имен, но и о реализации объектов.
Кроме того, заголовок буста содержал дезинформацию, которая ввела меня в заблуждение.
Согласно комментарию в источнике, вызов import_array() уже выполнен в numpy::initialize():
Но на самом деле, как оказалось, import_array() необходим.namespace boost { namespace python { namespace numpy { /** * @brief Initialize the Numpy C-API * * This must be called before using anything in boost.numpy; * It should probably be the first line inside BOOST_PYTHON_MODULE. * * @internal This just calls the Numpy C-API functions "import_array()" * and "import_ufunc()", and then calls * dtype::register_scalar_converters().
*/ BOOST_NUMPY_DECL void initialize(bool register_scalar_converters=true); }}} // namespace boost::python::numpy
Кроме того, были проблемы с тестированием изменений, так как куски кода с numpy (ранее с boost::python::numeric) вообще не покрывались тестами, а сам код также использовался в другом компоненте.
Поэтому проблемы были выявлены только при тестировании соответствующего компонента.
Команда интеграции не обязана писать тесты для компонентов, и эта ситуация была недосмотром самой команды.
Ух ты, я услышал от них достаточно, чтобы взломать их код. Но после некоторого ворчания со стороны команды они наконец покрыли свой код тестами.
Однако обида осталась (во время следующей миграции команда не захотела давать права доступа к своему компоненту моему коллеге, упомянув, что в прошлый раз мы взломали их код. Саша, извини! Но после трёх дней переговоров они сдались).
Заключение
После проделанной работы могу отметить для себя плюсы, так как раньше не часто пользовался boost (в основном std), поэтому могу выделить много нового из миграции.Забавно, но факт, после этого вы почему-то по умолчанию становитесь «экспертом по бусту» для многих коллег, и, смиритесь, какое-то время вам будут задавать вопросы по этому поводу.
Кстати, в последние годы многие компании начали активно избавляться от boost и заменять его по возможности на std-библиотеку, либо на что-то другое при отсутствии некоторых возможностей в стандартной библиотеке.
И мы тоже не остались в стороне.
Процесс начался, но не завершен, впереди еще много работы.
Теги: #программирование #C++ #boost #boost::filesystem #boost::numpy #boost::python #boost-1.65.1
-
Зачем Бизнесу Нужна Открытость?
19 Oct, 24 -
Микроапплеты
19 Oct, 24 -
С Днём Тестировщика!
19 Oct, 24