现有一个进程,依赖 libcurl.so 。此进程要接入一个 sdk,sdk 也依赖 curl。如果使用 curl 的静态库编译一个静态库 sdk,sdk 集成到进程后会不会有问题。此时原进程的 curl 地址空间和 sdk 集成的 curl 的地址空间完全独立?
得看 sdk 的编译参数;默认参数下应该是 sdk 用一套 libcurl,你的进程用一套 libcurl,两套 curl 独立;
但是 sdk 编译时候用--whole-archive 静态链接 libcurl.a 的话,libcurl 的名空间可以全暴露出来,可以给你的进程链接,如果要避免这个情况可以用--no-whole-archive
一般来说两种方法:
1. SDK 不要静态链 curl,链接 executable 的时候先链接 SDK,最后链接 libcurl.so ,这样整个进程使用同一份 libcurl 动态库;
2. 编译 SDK 成动态库,同时静态链接 libcurl,但是将 libcurl 符号全部隐藏(使用 ld script 控制);最后链接 executable 时分别链接 SDK.so 和 libcurl.so 。这样 SDK 当中使用的是自身静态链接的 curl,executable 其他部分使用的是动态链接的 libcurl.so ,不会冲突(前提是保证 SDK 中的 curl 的 symbol 全部隐藏);
如果 SDK 必须编译成静态库,那么选择方法 1 是最方便的。如果必须使用两个版本的 libcurl,可以使用方法 2.
谢谢回复。请教另外一个问题,编一个动态库,它依赖另外一个静态库,那么此动态库是不是会直接包含静态库代码?编好之后外部直接引用动态库,与静态库不再发生联系吧
不要这样做,这会浪费大量内存。降低用户体验。
尽量重用动态库,因为动态库实质上只有一份装入了内存,并使用写时复制技术保护。
是的。生成动态库的时候,所依赖的静态库部分都编进去了。没用到的静态库部分不会编进去。如果需要把静态库的所有内容都强制放到动态库里,可以加上 whole-archive 选项。最终动态库的使用方肯定都不需要再用到这个静态库了。