静态变量和全局变量在Linux上显示动态库和静态库的地址不同?
Both static variables and global variables show different addresses in dynamic library and static library on Linux?
我在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.cpp
和A.h
中声明的变量a
和b
.这是程序在我的机器上的结果:
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
。谁能回答我的问题,或者帮助找出程序中的一些错误(如果有的话)?
顺便说一句,老实说,在我正在做的另一个项目中,我发现全局变量的地址在动态库和静态库中是相同的。但是那个项目太大了,我无法提供一个小程序来重现这个行为。
非常感谢!
您显示的第一个命令构建了一个共享对象 d.so
。根据您问题的上下文,我推测您还打算 link 和 d.so
,但您的第二个命令似乎缺少该部分。我假设这是一个打字错误,因为这是对您显示的程序输出的唯一解释 - A.cpp
既 link 直接编辑,也内置到您的 d.so
图书馆。
鉴于此,引用您 link 编辑的文章:
Object code routines used by both should not be duplicated in each.
This is especially true for code which use static variables such as
singleton classes. A static variable is global and thus can only be
represented once. Including it twice will provide unexpected results.
但这正是您似乎违反的规则,您在 d.so
和 d.so
中两次表示 A
class 的静态范围实例主应用程序可执行文件。
所以,这似乎是指定的结果:"unexpected results"。
我在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.cpp
和A.h
中声明的变量a
和b
.这是程序在我的机器上的结果:
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
。谁能回答我的问题,或者帮助找出程序中的一些错误(如果有的话)?
顺便说一句,老实说,在我正在做的另一个项目中,我发现全局变量的地址在动态库和静态库中是相同的。但是那个项目太大了,我无法提供一个小程序来重现这个行为。
非常感谢!
您显示的第一个命令构建了一个共享对象 d.so
。根据您问题的上下文,我推测您还打算 link 和 d.so
,但您的第二个命令似乎缺少该部分。我假设这是一个打字错误,因为这是对您显示的程序输出的唯一解释 - A.cpp
既 link 直接编辑,也内置到您的 d.so
图书馆。
鉴于此,引用您 link 编辑的文章:
Object code routines used by both should not be duplicated in each. This is especially true for code which use static variables such as singleton classes. A static variable is global and thus can only be represented once. Including it twice will provide unexpected results.
但这正是您似乎违反的规则,您在 d.so
和 d.so
中两次表示 A
class 的静态范围实例主应用程序可执行文件。
所以,这似乎是指定的结果:"unexpected results"。