[工程构建] 动态库中的静态变量和全局变量在工程中的可见性(windows和linux有别)

ODR (One Definition Rule) :在“链接”的时候,全局变量在符号表中的符号必须唯一。

静态全局变量和函数不能被模块外部访问(这里的模块是指 动态库和可执行文件),这就意味着
如果某个第三方库的某个文件中定义了一个静态全局变量,那么无论如何调用这个库的程序都
看不到这个变量。
注意这里是  静态“全局”变量/函数。在名称空间内的静态成员可以通过名称空间来访问。

当使用extern来引入其他编译单元的符号时,Windows和Unix-like 的差别就出现了。


=================== 静态链接动态库的场景 ===================
在Windows环境下,exe和dll中的全局变量不会被纳入到导出符号中,这就是说,如果第三方
库中有一个全局变量,那么可执行程序在使用这个第三方库的时候是看不到这个全局变量的,
即便是我知道有这么个变量,在通过 extern 来声明使用,也是不可行的,会在连接时报错找
不到符号。
为了在windows环境下能够访问这样的全局变量,windows提供了导出符号表文件,即动态库
的伴生文件 .lib文件,这个文件会将全局变量纳入到符号表中。
而这个文件中有哪些内容就需要用  __declspec(dllexport) 和 __declspec(dllimport)来标注
这便是windows __declspec的由来

    #ifdef COMPILING_THE_DLL
    #define MY_DLL_EXPORT extern "C" __declspec(dllexport)
    #else
    #define MY_DLL_EXPORT extern "C" __declspec(dllimport)
    #endif
    
    MY_DLL_EXPORT int my_global; 

在Unix-like环境下,比如linux,编译时链接动态库其实是和链接静态库是一样的,因此需要
遵循ODR原则,又linux环境下不需要自行导出符号表,所以编译时所有全局变量都会被纳入到
符号表中,因此在linux环境下生成动态库不需要再创建一个.lib文件来描述符号表。


=================== 动态链接动态库的场景 ===================
动态链接动态库时,windows和linux是一样的,不需要关心符号表的导入、导出、冲突等问题,
只需要用  LoadLibrary() / GetProcAddress() / FreeLibrary() or dlopen() / dlsym() / dlclose()
等函数加载动态库,然后查找相应符号的位置,然后获取符号对应的地址即可。


=================== 最后 ===================
global variables should be avoided,dynamic libraries are not really defined by the C++ 
standard, this is platform-specific territory, meaning it is much less reliable / portable

原文:

https://stackoverflow.com/questions/19373061/what-happens-to-global-and-static-variables-in-a-shared-library-when-it-is-dynam?r=SearchResults

猜你喜欢

转载自blog.csdn.net/ykun089/article/details/107382749
今日推荐