Сегодня я ищу какое-то просветление о глубокой магии внутри динамического загрузчика. Я отлаживаю/устраняю неполадки системы плагинов для приложения C++, работающего в Linux. Он загружает плагины через dlopen
(RTLD_NOW | RTLS_LOCAL) и выпускает их через dlclose
. Ничего экстраординарного - можно было бы подумать.
Однако я заметил, что некоторые подключаемые модули остаются загруженными даже после успешного вызова dlclose
*. Я пришел к такому выводу после просмотра карты памяти запущенного процесса с помощью pmap. Некоторые библиотеки немедленно удаляются из памяти процесса, а другие остаются, по-видимому, на неопределенный срок.
Далее на справочной странице dlopen говорится:
Функция dlclose() уменьшает счетчик ссылок на дескриптор дескриптора динамической библиотеки. Если счетчик ссылок падает до нуля и никакие другие загруженные библиотеки не используют в нем символы, то динамическая библиотека выгружается.
Это означает, что проблема сводится к этим двум возможностям; Либо количество ссылок не равно нулю, либо другие загруженные библиотеки используют символы из некоторых, но не всех, плагинов.
Я почти уверен (хотя и не на 100%), что счетчики ссылок равны нулю. Менеджер плагинов приложения обрабатывает все плагины одинаково. Это также гарантирует, что плагин не будет загружен несколько раз. Поэтому загрузка и выгрузка IMO должны вести себя одинаково для всех плагинов.
Это оставляет вторую возможность: другие загруженные библиотеки используют символы из плагинов. Еще один типичный случай «Этого никогда не должно случиться». Хотя конечно возможно. Мы используем gcc и видимость по умолчанию, и, насколько я знаю, ничего не удаляется, поэтому экспортируются тонны символов. На самом деле это беспокоит меня гораздо больше, так как эти плагины должны быть независимыми.
Вот мои открытые вопросы на данный момент:
- Верны ли мои выводы на данный момент?
- Знаете ли вы, как проверить счетчик ссылок для verify
dlopen
? - Если есть внутренние символы моих плагинов (случайно), используемые другими библиотеками, есть ли способ отследить, кто какие символы использует?
Моя машина: Linux 3.13.0-43-generic #72-Ubuntu SMP, понедельник, 8 декабря, 19:35:44 UTC 2014 i686 i686 i686 GNU/Linux
* Я должен упомянуть, что вся загрузка и выгрузка происходят в основном потоке, поэтому здесь не должно быть проблем с многопоточностью.
ltrace
и/илиstrace
, чтобы понять, по крайней мере, когда загружаются общие объекты. - person Basile Starynkevitch   schedule 10.04.2015valgrind
или скомпилируйте сgcc -fsanitize=address
; у вас куча может быть повреждена! - person Basile Starynkevitch   schedule 10.04.2015