我正在使用某些GNU工具,即GNU C++编译器(g++)和GNU Linker (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定义前面的"T“表示该方法驻留在文件的文本/代码部分。
类似地,如果我在共享库文件上运行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*
>
>
>&
)这看起来也很好。类方法ToolboxManager::registerToolbox定义前面的"U“表示该方法在共享库文件中未定义。
但是,当我从命令行运行二进制可执行文件时,出现了一个问题,该问题导致显示以下错误消息;
./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就是这一个;
-Wl,--export-dynamicGNU链接器选项指示--export-dynamic链接器向动态符号表添加所有符号。
然后再次运行二进制可执行文件。这一次,它正确地执行了,并且对dlopen函数的调用没有导致未定义的符号错误。这让我非常困惑,因为它看起来像是在二进制可执行文件的初始版本中正确地导出了符号。有没有人能看到这里的问题?任何帮助都将不胜感激。
提前谢谢。
发布于 2011-09-14 07:09:42
我已经设法解决了这个问题。我发现如果我去掉下面一行中的引号;
"ToolboxManager::registerToolbox*"在文件${top_srcdir}/dynamic_symbol_table.txt中,然后重新链接二进制可执行文件,然后它就可以工作了。也就是说,dlopen函数将不再失败。
我不禁想知道,在GNU binutils邮件列表上问这个问题是否比在这个网站上问这个问题更合适。
https://stackoverflow.com/questions/7395838
复制相似问题