Я сталкивался на CentOS 6.5. Как я искал в Интернете, статическая переменная ведет себя по-разному в Windows и в Linux при использовании динамической библиотеки. Таким образом, Windows вызовет дублирование переменных, а Linux — нет, например:
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
Однако, когда я написал небольшую программу для проверки этого, я обнаружил, что Linux также вызывает дублирование. Вот моя маленькая программа, включающая четыре файла:
(1) А.ч
#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
в динамической части. Кто-нибудь, пожалуйста, ответьте на мой вопрос или помогите найти ошибки в программе (если есть)?
Кстати, если честно, в другом проекте, над которым я работаю, я обнаружил, что адреса глобальных переменных одинаковы в динамической и статической библиотеках. Но этот проект слишком большой, и я не могу предоставить небольшую программу для воспроизведения поведения.
Большое спасибо !
Первая команда, которую вы показали, создает общий объект d.so
, Исходя из контекста вашего вопроса, я полагаю, что вы также намеревались связаться с d.so
, но ваша вторая команда, кажется, пропустил эту часть. Я предполагаю, что это опечатка, так как это единственное объяснение вывода программы, которую вы показали — что A.cpp
связан как напрямую, так и встроен в ваш d.so
библиотека.
Учитывая это, цитата из статьи, на которую вы ссылались:
Подпрограммы объектного кода, используемые обоими, не должны дублироваться в каждом.
Это особенно верно для кода, который использует статические переменные, такие как
синглтон классы. Статическая переменная является глобальной и поэтому может быть только
представлены один раз. Включение его дважды даст неожиданные результаты.
Но это именно то правило, которое вы, кажется, нарушаете, вы представляете статически ограниченный экземпляр A
класс в два раза, в вашем d.so
и в вашем основном приложении исполняемый файл.
Таким образом, это, кажется, указанный результат: «неожиданные результаты».
Других решений пока нет …