I have encountered on CentOS 6.5. As I have searched online that static variable behaves differently on Windows and on Linux when using dynamic library. That is, Windows would cause duplication of variables and Linux would not, like this one: http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
However, when I wrote a small program to validate this, I found that Linux also causes duplication. Here is my small program, including four files:
(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; }
Here is how I compile and run my program:
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
Both the dynamic part d.cpp
and the static part main.cpp
use the variables a
and b
declared in A.cpp
and A.h
. And here is the result of the program on my machine:
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
This surprises me a lot, because the addresses of global variable a
and static variable b
should be the same in the dynamic part and the static part. And it seems that modification on a
in static part does not effect the a
in dynamic part. Would anyone please answer my question, or help find out some mistakes in the program (if any)?
By the way, to be honest, on another project I am working on, I find that addresses of global variables are the same in dynamic library and in static library. But that project is too big and I cannot provide a small program to reproduce the behavior.
Thanks a lot !
The first command you showed builds a shared object d.so
. Based on the context of your question, I surmise that you also intended to link with d.so
, but your second command seems to be missing that part. I'm assuming that it's a typo, as this is the only explanation for the program output you showed -- that A.cpp
is both linked to directly, and is also built into your d.so
library.
Given that, quoting from the article you linked:
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.
But that's exactly the rule you seem to be breaking, you're representing the statically-scoped instance of the A
class twice, in your d.so
, and in your main application executable.
So, that seems to be the indicated outcome: "unexpected results".