Использование перегруженных new / delete и STL в разделяемой библиотеке - PullRequest
0 голосов
/ 22 апреля 2020

Я столкнулся с проблемой, которая была вызвана соединением перегруженных операторов new / delete и STL (особенно std: : строка). Вот мой случай ...

Я компилирую разделяемую библиотеку (назовите ее libfoo.so), в которой я перегружаю операторы new и delete . Чтобы не влиять на программу, которая будет использовать эту библиотеку, я сделал символы new и delete скрытыми. Также моя библиотека использует STL, особенно std :: string, который, как я ожидаю, должен использовать мои операторы new / delete , так как это класс шаблона.

Когда я компилирую библиотека с -O1 и выше, я получаю SIGABRT, который был вызван использованием различных операторов new / delete в конструкторе / деструкторе basic_string. new вызывается из libstdc ++., Но delete вызывается из моей библиотеки.

Когда я компилирую библиотеку с -O0 или -fno-inline операторы new / delete для конструктора / деструктора basic_string оба вызываются из libstdc ++.

Я сделал минимальный пример, который демонстрирует такое поведение: https://github.com/yekatkov/CustomNewDelete
Шаги для воспроизведения ошибки находятся в Readme.md.

Это нормальное поведение оптимизации? Или, может быть, я должен использовать std :: string по-другому? Как заставить классы stl в моей библиотеке использовать мои new / delete ? Предположим, что моя настоящая библиотека имеет тонны классов stl, поэтому я не могу переопределить распределитель для каждого из них. : (

Я использую glib c 2.27, г cc 5.5.0

Буду рад выслушать любые идеи:)

Спасибо!

1 Ответ

2 голосов
/ 22 апреля 2020

Ваша базовая c проблема в том, что вы пытаетесь создать несколько разных глобальных operator new s, один в вашем dylib, а другой для всех, кто использует ваш dylib.

Может быть только один , Вот почему он называется оператором global .

Если у вас их больше одного, вы можете получить то поведение, которое видите. (Или что-то еще, вы идете в UB-страну здесь)

(позже) И libstdc ++, и libc ++ внешне создают std::basic_string<char, std::char_traits<char>, std::allocator<char>> (он же std::string) в dylib. Это означает, что когда вы вызываете не встроенные методы в string, вы запускаете код из dylib, который НЕ будет использовать ваш скрытый оператор new / delete для выделения / освобождения памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...