我在CentOS 6.5上遇到过。正如我在网上搜索的那样,静态变量在使用动态库时在Windows和Linux上表现不同。也就是说,Windows会导致变量重复,Linux不会像这样: http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
但是,当我编写一个小程序来验证这一点时,我发现Linux也会导致重复。这是我的小程序,包括四个文件:
(1)A.h
#ifndef A_H #define A_H #include <cstdio> static int b; extern "C" class A { public: int mem; A() { printf("A's address: %p\n", this); printf("B's address: %p\n", &b); } void print() { printf("%p: %d\n", this, mem); } ~A() { printf("DELETE A!!!!! %p\n", this); } }; extern A a; #endif
(2)A.cpp
#include "A.h" A a;
(3)d.cpp
#include "A.h" extern "C" void exec() { a.print(); }
(4)main.cpp
#include "A.h" #include <dlfcn.h> typedef void (*fptr) (); int main() { a.mem = 22; a.print(); void *handle; handle = dlopen("d.so", RTLD_LAZY); fptr exec = reinterpret_cast<fptr>(dlsym(handle, "exec")); (*exec)(); dlclose(handle); return 0; }
以下是我编译和运行程序的方法:
g++ d.cpp A.cpp -shared -rdynamic -o d.so -ldl -I. -fPIC -g -std=c++1y g++ main.cpp A.cpp -ldl -I. -g -std=c++1y ./a.out
动态部分d.cpp
和静态部分main.cpp
都使用a
和b
中声明的变量A.cpp
和A.h
。以下是我机器上程序的结果:
A's address: 0x600f8c B's address: 0x600f90 0x600f8c: 22 A's address: 0x7fb8fe859e4c B's address: 0x7fb8fe859e50 0x7fb8fe859e4c: 0 DELETE A!!!!! 0x7fb8fe859e4c DELETE A!!!!! 0x600f8c
这让我感到非常惊讶,因为全局变量a
和静态变量b
的地址在动态部分和静态部分中应该相同。并且似乎静态部分中a
上的修改不会影响动态部分中的a
。有人请回答我的问题,或者帮助找出程序中的一些错误(如果有的话)?
顺便说一句,老实说,在我正在研究的另一个项目中,我发现全局变量的地址在动态库和静态库中是相同的。但是这个项目太大了,我无法提供一个小程序来重现这种行为。
非常感谢!
答案 0 :(得分:0)
您展示的第一个命令构建了一个共享对象d.so
。根据您的问题的背景,我猜测您还打算与d.so
链接,但您的第二个命令似乎缺少该部分。我假设它是一个错字,因为这是您显示的程序输出的唯一解释 - A.cpp
直接链接到,并且也内置到您的{{1}库。
鉴于此,请引用您链接的文章:
两者使用的对象代码例程不应在每个例程中重复。 对于使用静态变量的代码尤其如此 单身课程。静态变量是全局的,因此只能是 代表一次。包括它两次将提供意想不到的结果。
但这正是你似乎要破坏的规则,你在d.so
和你的A
两次代表d.so
课程的静态范围实例主要应用程序可执行文件。
所以,这似乎是指示的结果:&#34;意外的结果&#34;。