C语言解决动态库符号冲突

问题:主程序中使用了静态库A,主程序使用的动态库B中也使用了静态库A。程序运行时先加载了主程序静态库A的符号,动态库B在运行到静态库A的代码时(错误地运行了主程序静态库A的符号)出现crash。

解决:动态库B在编译时添加-Wl,-Bsymbolic选项,这是个链接选项,连接器ld会使so优先使用库内符号

-Bsymbolic
    When creating a shared library, bind references to global symbols to the definition within the shared library, if any.  Normally, it is possible for a program linked against a shared library to override the definition within the shared library.  This  option is only meaningful on ELF platforms which support shared libraries.

译文:在创建共享库时,将对全局符号的引用绑定到共享库中的定义(如果有的话)。通常,链接到共享库的程序可以覆盖共享库中的定义。这个选项只在支持共享库的ELF平台上有意义。
如果动态库B先加载,需要保证自身不会覆盖其他库或程序的符号,因此在编译动态库时需要添加-fvisibility=hidden选项,该选项会隐藏动态库的所有符号,所以需要在源码中对需要导出的函数和变量前加上__attribute__ ((visibility ("default")))属性
拓展:隐藏静态库的符号
选项:-Wl,--exclude-libs,ALL

### 动态加载解决SM2不同版本间冲突的方法 为了处理SM2加密库的不同版本之间可能出现的符号冲突问题,可以采用动态加载的方式来隔离各个版本的库文件。这种方式能够有效防止全局命名空间污染以及避免静态链接时产生的符号覆盖。 #### 使用dlopen函数族实现按需加载特定版本的共享对象 在Linux环境下,可以通过POSIX标准定义的一组接口(`dlopen`, `dlclose`, `dlsym`)来进行运行时刻的动态链接操作: - 加载指定路径下的.so文件而不立即解析其中未定义符号- 获取已加载模块内某个符号对应的地址; - 卸载不再需要的共享目标文件。 具体来说,在应用程序启动初期并不急于初始化任何一种版本的安全机制,而是等到真正需要用到该功能之时再决定打开哪一个具体的实现库并从中获取必要的入口点指针。 ```c #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> typedef void (*sm2_encrypt_func)(const char *input, size_t input_len); int main() { void* handle; sm2_encrypt_func encrypt; // Load the shared object file at runtime. handle = dlopen("./libsm2_v1.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(EXIT_FAILURE); } // Reset errors and get symbol address from loaded library. dlerror(); *(void **)(&encrypt) = dlsym(handle, "sm2_encrypt"); const char *dlsym_error = dlerrpr(); if (dlsym_error != NULL) { fprintf(stderr, "%s\n", dlsym_error); dlclose(handle); exit(EXIT_FAILURE); } // Use the function as needed... // Close the library when done with it. dlclose(handle); } ``` 上述代码展示了如何利用C语言编写程序来安全地调用两个不同版本的SM2库之一而不会引起相互干扰[^1]。 对于Java环境而言,则可借助JNI(Java Native Interface)技术同样达成相似效果——即先编译好针对每种BC提供者封装后的本地方法存根(.so),之后由上层应用依据实际需求选择性导入相应组件完成整个流程控制逻辑的设计与实施[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值