避免 unix 中的标准库冲突

Posted

技术标签:

【中文标题】避免 unix 中的标准库冲突【英文标题】:Avoiding standard library conflicts in unix 【发布时间】:2018-06-25 15:15:27 【问题描述】:

我有一个共享库 (so) 对象,它公开了一个 C API (extern "C")。它不在 API 中使用 C++,也不抛出异常。在内部,它确实使用了 C++,尤其是 std::map 和其他容器,以及一些琐碎的模板。

我的目标是能够将此库提供给 unix 中的任何程序(我为每个目标 linux 发行版编译多个版本),而不会与加载程序(即使用 @987654325 加载我的库的程序)存在标准库符号问题@ 应该可以正常工作,即使它是用另一个版本的标准库编译的)。

这是我通过阅读所做的:

    静态链接 libstdc++ 和 libgcc

    使用链接器脚本将所有符号标记为本地符号,但从 API 导出的 C-ABI 符号除外

    linker_script.lds
    
      global: my_api_func;
      local: *;
    
    

g++ shared.cpp -Wl,--version-script=vs.lds -fPIC -static-libstdc++ -static-libgcc -shared -o libshared.so

此时我的问题是:如果加载程序使用不同(主要/次要/完全不同)版本的标准库,这是否足以让我在内部使用 C++ 并避免所有冲突?如果我使用 C++14 或更新的版本并遵循上述程序会怎样?

【问题讨论】:

我通常会看到程序在一些“$LIB”文件夹中发布它们自己的库版本,然后使用LD_PRELOAD="/usr/$LIB/libstdc++.so.6 ....",如steam。我想使用 docker 或 snaps 是一种方法。 @KamilCuk 这太恶心了。他们应该了解-Wl,-rpath=$ORIGIN 【参考方案1】:

此时我的问题是:如果加载程序使用不同(主要/次要/完全不同)版本的标准库,这是否足以让我在内部使用 C++ 并避免所有冲突?

应该够了。但一定要验证:

    std::nm -C --undefined-only <my.so> 中没有意外的未定义符号。 您的库不会使用nm -C --defined-only --extern-only <my.so> 从 C++ 标准库中导出任何符号。以及您不希望它导出的任何符号。 readelf -d <my.so> 没有意外的必需共享库。

如果我使用 C++14 或更新的版本并遵循上述程序会怎样?

只要您验证您的库使用和导出哪些符号,此方法就可以正常工作。

【讨论】:

以上是关于避免 unix 中的标准库冲突的主要内容,如果未能解决你的问题,请参考以下文章

Unix环境高级编程标准I/O库

UNIX环境高级编程 标准IO库

python常用标准库(时间模块time和datetime)

VS2017 #error: : snprintf 的宏定义与标准库函数声明冲突

如何在 Unix 上包含 «pty.h» 头文件/将 «pty.h» 添加到标准库 C / C++

Python3标准库:fnmatch UNIX式glob模式匹配