*修改了问题(见下文)*
我有一个cpp文件,定义一个静态的全局variables,例如
静态Foo吧;
这个cpp文件被编译成可执行文件和共享库。 可执行文件可能会在运行时加载共享库。
如果我在Linux上似乎有这个variables的两个副本。 我假设一个来自可执行文件,一个来自共享库。 其他平台(惠普,Windows)似乎只有一个副本。
什么控制这种行为在Linux上,我可以改变它? 例如,是否有一个编译器或链接器标志,将强制共享库中的此variables的版本是从可执行文件相同?
*修改问题*
感谢迄今为止的答案。 重新审视这个问题实际上并不是上述的问题。 上面的静态全局variables确实在Windows上有多个副本,所以与我在Linux上看到的没有任何区别。
不过 ,我有另一个全局variables(这次不是静态的),这是在一个cpp文件中声明,并在头文件中作为extern。
在Windows上,这个variables有多个副本,一个在可执行文件中,一个在每个dll中加载,在Linux上只有一个。 所以现在的问题是关于这个区别。 我怎样才能让Linux有多个副本?
(我的程序的逻辑意味着静态全局variables的值取决于非静态全局variables的值,我开始指责错误variables是问题)
我强烈建议你阅读以下内容 。 之后,您将了解有关Linux中共享库的一切。 正如其他人所说,快速的答案是static
关键字会将全局变量的范围限制到翻译单元(从而限制到可执行文件或共享库)。 在头文件中使用关键字extern
,并且仅在其中一个模块(exe或dll / so)中编译包含相同全局变量的cpp将使全局变量唯一并在所有模块之间共享。
编辑:当您使用extern
模式的Windows上的行为是不一样的Linux,因为Windows加载动态链接库(DLL)的方法是不一样的,基本上是不能动态链接全局变量(这样只有一个存在)。 如果你可以使用DLL的静态加载(不使用LoadLibrary
),那么你可以使用下面的代码:
//In one module which has the actual global variable: __declspec(dllexport) myClass myGlobalObject; //In all other modules: __declspec(dllimport) myClass myGlobalObject;
这将使myGlobalObject
在所有使用上述第一个版本的DLL的模块中唯一和共享。
如果您希望每个模块都有自己的全局变量实例,那么使用static关键字,则对于Linux或Windows,行为将是相同的。
如果你想要一个全局变量的唯一实例并且需要动态加载( LoadLibrary
或者dlopen
),你将不得不做一个初始化函数来为每个加载的DLL提供一个指向全局变量的指针(在它被使用之前)。 你还必须保留一个引用计数(你可以使用shared_ptr
),这样你就可以在没有引用计数时创建一个新的引用计数,否则就增加计数,并且当计数为零时可以删除它,因为DLL是被卸载。
应用于命名空间变量的static
限定符意味着变量的范围是翻译单元。 这意味着如果这个变量是在一个头文件中定义的,并且你从多个.cpp文件中包含它,你将会得到一个副本。 如果你想要一个副本,那么在标题中将其标记为extern
(而不是static
),将其定义在一个单独的翻译单元中,并将其链接到可执行文件或库(但不是两者)。
你在每个平台上使用了什么编译器? 你所描述的Linux的行为应该是我所期望的,静态的全局只在编译时在那个特定的文件中是本地的。
您可以使用GCC visibility
属性或visibility
附注来解决您的问题
我不知道HPUX,但是在Windows上,如果你有一个exe和一个DLL,并且他们每个声明全局变量,那么将会有两个不同的变量。 如果您只获取一个变量,则一个图像必须从另一个图像导入变量。