【发布时间】:2017-12-16 01:41:31
【问题描述】:
假设应用程序myapp.exe 是使用g++ 构建的,并且它使用标志-static-libstdc++,因此它可以安装在没有libstdc++.so 的环境中。 myapp.exe 还添加了对某些函数 plugf 的插件支持,这些函数可以通过 dlopen 从分片库中动态加载。
如果libplug.so 是这样一个插件库,它也链接到libstdc++,它如何以能够与myapp.exe 一起工作的方式这样做?
如果libstdc++ 是动态链接的,这很简单,因为myapp.exe 和libplug.so 都可以使用相同的动态加载的标准库,但我不清楚如何最好地使用静态链接的标准库来做到这一点。
我正在考虑的一种方法是让libplug.so 也使用标志-static-libstdc++,然后使用version script
{
global: plugf;
local: *;
};
以确保使用它的标准库版本,但这意味着将有两个libstdc++ 的副本加载到内存中。我知道这种方法不会受到 C++ 标准的祝福,因为它会违反 ORD,但是libstdc++ 以任何方式支持它吗?其manual 部分的Multiple ABI testing 部分确实引用了一个听起来相似的场景。
【问题讨论】:
-
遗憾的是,您将需要分发一个动态/静态链接的 libstdc++ 以匹配
libplug.so- 是的,将在运行时加载两个副本。是的,如果你的插件返回一个带有一个版本的 libstdc++ 的指针,而你用另一个版本释放它,你可能会遇到麻烦。 -
我认为这不是真的。分配由标准 c 库处理,
-static-libstdc++不会导致libc静态链接,因此它们都使用相同的libc.so。 -
我认为在 libstdc++ 中对象是用
__gnu_cxx::new_allocator分配的,也许正如您指出的那样,它们都指向同一个libc.so。根据个人经验,我在使用 MSVC 的 RT 时遇到了上述问题。 -
诸如
new int{123}之类的标准分配调用operator new,在libstdc++ 中它只是malloc 的一个包装器。 (见here)。 -
是的,取决于你如何构建它,例如你可能混合了不同版本的 libc。这就是为什么 HDL 之类的库不公开内存分配的原因。无论如何,支持动态插件的系统依赖于动态库确实避免了重复。这就是发明 dll 的原因。减轻部署策略影响的一种方法是严重依赖 LTO。