首先,简单说明下问题情境,一共三个代码文件,一个主执行程序,两个动态库程序,结构与之前写的弱符号,weak symbol一致:
#include <string>
std::string g_name;
void init_name_lib1()
{
g_name = "lib1";
}
const char* get_name_lib1()
{
return g_name.c_str();
}
#include <string>
std::string g_name;
void init_name_lib2()
{
g_name = "lib2";
}
const char* get_name_lib2()
{
return g_name.c_str();
}
#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;
}
编译运行命令也与之前那篇基本一样:
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<<处理后发布,原文只有博主可以看到。