2

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 !

Zhao Yunjian
  • 137
  • 9

1 Answers1

0

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".

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Thanks for your answer! You're right. The first cmd line generates a `d.so`, but I don't think I've linked it in a wrong way. There are two ways to link a dynamic library. One is to link when compiling the program, the other is to use `dlopen`, `dlsym` and `dlclose`. (http://linux.die.net/man/3/dlopen) I use the latter one, as shown in `main.cpp`. (I mean that's not a typo, the cmd lines are executable on my machine ^_^). But ... you do make me think whether `dlopen` will cause duplication of object code routines. – Zhao Yunjian Nov 10 '15 at 03:31
  • dlopen -- definitely. dlopen opens the indicated shared library and maps it into the executable's address space. dlopen has absolutely no logic, whatsoever, to determine if the executable defines the same symbols as the shared library, and somehow don't load them from the shared library. Either the entire library gets loaded, or not. – Sam Varshavchik Nov 10 '15 at 12:05
  • `dlopen` really creates new copies of global variables in dynamic part, which are different from the ones in static part. – Zhao Yunjian Nov 26 '15 at 05:41