Мировой уровень

Nov 11, 2024 22:08

В одной части одной довольно широко известной БД используется штука под названием boost::ptr_vector. Хранит он массив указателей, приведённых к void*.

Этот класс, если вы делаете его копию, выполняет копирование элементов. Если у типа элементов нет метода clone(), то выполняется new() и присваивание (копирование). При удалении объекта типа boost::ptr_vector, выполняется поэлементный delete. Легко увидеть, что если в данных элементов есть указатель на объект, что не обёрнут в умный указатель, то он может быть освобождён дважды (и более раз).

Само собой, использование этой структуры было выполнено на высочайшем уровне: метода clone() у типов элементов не было, и происходило двойное освобождение памяти. Как легко догадаться, это приводило к редким отказам по разным причинам, в самом конце (правильного, в том числе) выполнения программы, когда удалялся всеобъемлющий объект. Отказ мог быть нарушением защиты памяти (SIGSEGV), а мог быть аварийным прекращением работы программы (SIGABORT).

Для обеих случаев отказа, наши предшественники использовали обработчики сигналов, фактически заметая проблему под ковёр.

Мои исправления что-то сдвинули и аварийное завершение стало виснуть на записи, заставляя программу висеть и заставлять MTR отстреливать тест, а не бодро отваливаться, позволяя продолжать как-то. И вот теперь я снова вынужден исправлять ошибку более, чем 10-летней давности.

программисты, ошибки программ, программирование, работа

Previous post Next post
Up