Я использую некоторые инструменты GNU, например, компилятор GNU C ++ (g ++) и компоновщик GNU (ld) для создания файла общей библиотеки (.so), а также двоичного исполняемого файла.
двоичный исполняемый файл использует функцию dlopen
для динамической загрузки файла общей библиотеки во время выполнения.В дополнение к этому, файл общей библиотеки должен вызывать определенный метод класса (называемый ToolboxManager::registerToolbox
), который определен в двоичном исполняемом файле.Это достигается путем принудительного выполнения двоичного исполняемого файла для экспорта метода класса, что, в свою очередь, выполняется во время компоновки путем связывания двоичного исполняемого файла со следующими параметрами командной строки:
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt
, где файл ${top_srcdir}/dynamic_symbol_table.txt
содержитследующее содержимое:
{
extern "C++"
{
"ToolboxManager::registerToolbox*";
};
};
Обратите внимание на использование звездочки (*) в файле, чтобы заставить компоновщик экспортировать все символы, начинающиеся с ToolboxManager::registerToolbox
.
Когда я запускаюУтилита GNU nm (nm -C -g ./a.out
) в результирующем двоичном исполняемом файле отображает следующую информацию о вышеупомянутом методе класса:
08053da0 T ToolboxManager::registerToolbox
(
std::string&,
std::string&,
std::map
<
std::string,
Factory_DSPB_Base*,
std::less
<
std::string
>,
std::allocator
<
std::pair
<
std::string const,
Factory_DSPB_Base*
>
>
>&
)
или, если утилита nm вызывается, как указано выше, но на этот разбез использования ключа командной строки -C;
08053da0 T _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
Пока все выглядит нормально.«Т» перед определением метода класса ToolboxManager::registerToolbox
означает, что метод находится в разделе «Текст / код» файла.
Аналогично, если я запускаю утилиту nm (nm -C -g ./toolbox.so
) в файле общей библиотеки он отображает следующую информацию о том же вышеупомянутом методе класса:
U ToolboxManager::registerToolbox
(
std::string&,
std::string&,
std::map
<
std::string,
Factory_DSPB_Base*,
std::less
<
std::string
>,
std::allocator
<
std::pair
<
std::string const,
Factory_DSPB_Base*
>
>
>&
)
Это также выглядит хорошо.«U» перед определением метода класса ToolboxManager::registerToolbox
означает, что метод не определен в файле общей библиотеки.
Однако возникает проблема, когда я запускаю двоичный файл, доступный для выполнения из командной строкии эта проблема приводит к отображению следующего сообщения об ошибке:
./toolbox.so: undefined symbol: _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
Имя метода искаженного класса, которое появляется в этом сообщении времени выполнения, показано ниже, как первая из двух строк.Для сравнения приведенное выше имя метода искалеченного класса (которое было сгенерировано с помощью команды nm -g
) показано ниже как вторая из двух строк;
_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
Как видно, два искалеченных имени идентичны.Поэтому я не могу понять, почему неопределенный символ не может быть разрешен во время выполнения.
Затем я повторно связал исполняемый файл двоичного кода, однако на этот раз я заменил следующую команду компоновщика:
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt
наthe this;
-Wl,--export-dynamic
Параметр компоновщика --export-dynamic
дает указание компоновщику GNU добавить все символы в таблицу динамических символов.
Если затем снова запустите исполняемый двоичный файл.На этот раз он выполнялся правильно, и вызов функции dlopen не привел к неопределенной ошибке символа.Это крайне озадачило меня, так как похоже, что символ правильно экспортируется в исходной версии двоичного исполняемого файла.Кто-нибудь может увидеть проблему здесь?Мы будем благодарны за любую помощь.
Заранее спасибо.