首先,简单说明下问题情境,一共三个代码文件,一个主执行程序,两个动态库程序,结构与之前写的弱符号,weak symbol一致:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <string> std::string g_name; void init_name_lib1() { g_name = "lib1" ; } const char * get_name_lib1() { return g_name.c_str(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <string> std::string g_name; void init_name_lib2() { g_name = "lib2" ; } const char * get_name_lib2() { return g_name.c_str(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <iostream> void init_name_lib1(); void init_name_lib2(); const char * get_name_lib1(); const char * get_name_lib2(); int main() { init_name_lib1(); init_name_lib2(); std::cout << "name from lib1: " << get_name_lib1() << std::endl; std::cout << "name from lib2: " << get_name_lib2() << std::endl; return EXIT_SUCCESS; } |
编译运行命令也与之前那篇基本一样:
1 2 3 4 5 6 | 1986 g++ -c -fpic cpp_lib2.cpp 1987 g++ -c -fpic cpp_lib1.cpp 1988 g++ -shared -o lib1.so cpp_lib1.o 1989 g++ -shared -o lib2.so cpp_lib2.o 1990 g++ -L./ main.cpp -l1 -l2 1991 LD_LIBRARY_PATH=./ . /a .out |
运行后会发现输出的两个lib库返回字符串一样,均为lib2(某些初始化方式,比如用fmt库时还有可能在主程序退出是出现double free异常)!其原因是因为linux下gcc默认动态库全部符号导出,而两个不同库中的全局变量g_name重名,因此在main主执行程序加载时,会出现后加载的覆盖掉先加载的情况(同名函数符号也一样,例如两个不同动态库同时用了同一个公共代码,但版本不同,这样就有可能导致其中一个库功能出现异常,因为调成了错误版本的同名函数!)。
知道了原因解决的办法就好说了,要不改下名字,或者套个不同的namespace,又或者加上static,隐藏进.o内部就可以了。
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。
加载更多