Russian Qt Forum
Ноябрь 23, 2024, 11:50 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с доступом к static переменной  (Прочитано 6078 раз)
jasf
Гость
« : Ноябрь 20, 2009, 02:08 »

Здравствуйте. Столкнулся с большой проблемой. За весь вечер ничего не нашёл (в том числе и в гугле).
Имеется 1 статическая, 1 динамическая (1 extern "C" функция ) дллка, и 1 ехешник. ехешник и дин. дллка слинкованны со статической дллкой.
в стат. дллке есть переменная int var;
*.h
extern int var;
*.cpp
int var = 1;
void QMyApplication::QMyApplication():QApplication(){var=2;}

т.е. как видно, класс приложения находится в стат. дллке, exeшник при запуске создаёт экземпляр данного класса, и var получает значение 2.

потом подгружается дин. дллка, и что мы видим? var в этой дллке имеет значение 1!  Злой Плачущий. Адрес переменной var в дин. дллке не совпадает с адресом из .exeшника. Т.е. явно видно, что дин.дллка заалоцировала и сиинициализирова свой участок памяти под var, когда как данная переменная уже есть в области данных процесса.
Взлянув в QCoreApplication::self, вижу - что адрес этой переменной, при доступе что из .ехе, что из дин. дллки не меняется.
адрес же всех статических переменных в моей стат. дллке - изменён.

покопав, так же заметил, что классы Qt (типа QWidget) задекларированы как __declspec(dllimport), что несколько удивило (Visual studio компилятор выдаёт ошибку при попытке повторения подвига).
помогите разобраться пожалуйста.

P.S. задекларировать эту var пытался очень по разному.. не помогло.
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #1 : Ноябрь 20, 2009, 04:55 »

она объявлена как
Код:
int var = 1;
или как
Код:
static int var = 1;
?
Записан
SASA
Гость
« Ответ #2 : Ноябрь 20, 2009, 09:58 »

В этом и есть отличие динамической линковки от статической. При статической линковке, каждый создаёт по экземпляру  данных и кода, а при динамической все пользуются общими. Т.е. если вашу статическую либку подключат три длл, то будает созданно три переменных var.
Записан
jasf
Гость
« Ответ #3 : Ноябрь 20, 2009, 10:00 »

ещё раз повторюсь, что как бы я её не объявлял.. эффекта ноль. все глобальные переменные, объявленные в стат. дллке изменяют свой адрес и реинициализируются в дин. дллке.
объявлена полностью по аналогии со static QCoreApplication* self;, т.е.

*.h
class MY_EXPORT_C QMYApplication : public QApplication
{
...
   static QMYApplication * mySelf;
};

*.cpp
QMYApplication * QMYApplication ::mySelf = 0;


#define MY_EXPORT_C __declspec(dllexport)

нет я конечно могу в QMyApplication создать хранилище, и через него реализовать глобальные переменные, но это ж ахтунг! сколько пользуюсь ими (глобальными переменными) на других платформах - никогда ничего подобного не встречал..
« Последнее редактирование: Ноябрь 20, 2009, 10:07 от jasf » Записан
jasf
Гость
« Ответ #4 : Ноябрь 20, 2009, 10:02 »

В этом и есть отличие динамической линковки от статической. При статической линковке, каждый создаёт по экземпляру  данных и кода, а при динамической все пользуются общими. Т.е. если вашу статическую либку подключат три длл, то будает созданно три переменных var.

тогда как сделано так, что даже если я подключаю дин. дллку, у QCoreApplication::self адрес остаётся неизменным? думается мне, что проблема в каких-то настройках компоновщика..

P.S. проект стат. дллки создан через визард. Всё по умолчанию.
« Последнее редактирование: Ноябрь 20, 2009, 10:11 от jasf » Записан
SASA
Гость
« Ответ #5 : Ноябрь 20, 2009, 10:13 »

тогда как сделано так, что даже если я подключаю дин. дллку, у QCoreApplication::self адрес остаётся неизменным?
ответ:
Код:
дин. дллку
Записан
jasf
Гость
« Ответ #6 : Ноябрь 20, 2009, 10:17 »

тогда как сделано так, что даже если я подключаю дин. дллку, у QCoreApplication::self адрес остаётся неизменным?
ответ:
Код:
дин. дллку

не понимаю. У меня есть в стат. дллке класс

class MY_EXPORT_C QMYApplication : public QApplication : public QCoreApplication

экзэмпляр создаётся в .ехешнике. В нём есть стат. переменная QCoreApplication::self. так вот когда я подключаю дин. дллку (через QLibrary), адрес QCoreApplication::self не изменяется, а адрес QMyApplication::mySelf изменяется. При этом например под Symbianом никогда подобного эффекта не было. Если я задекларировал mySelf в статик. длл, тогда могу из любого подключаемого модуля обращаться к этой переменной и у неё адрес изменяться не будет.
« Последнее редактирование: Ноябрь 20, 2009, 10:34 от jasf » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Ноябрь 20, 2009, 11:03 »

Цитировать
не понимаю. У меня есть в стат. дллке
статических дллок не бывает!
Записан

ArchLinux x86_64 / Win10 64 bit
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Ноябрь 20, 2009, 11:27 »

Тема интересная но трудно понять. Вы бы объяснили так

Код:
// static lib
...

Код:
// dll
...

Код:
// exe
...

А то путаница полная где кто
Записан
jasf
Гость
« Ответ #9 : Ноябрь 20, 2009, 12:38 »

exe.exe и dynamic.dll слинкованы со static.dll

static.dll
Код:
// static dll
///////////////////////////////////////////////////
//static.h
///////////////////////////////////////////////////
#ifndef STATIC_H
#define STATIC_H

#include <QObject>


class Q_DECL_EXPORT MyClass
{
public:
MyClass();
~MyClass();

public:
static MyClass* self;

};

class dyn_interface
{
public:
virtual MyClass** pself() = 0;
};

#endif // STATIC_H

///////////////////////////////////////////////////
static.cpp
///////////////////////////////////////////////////

#include "static.h"

MyClass* MyClass::self = (MyClass*) 0xabcdef;
MyClass::MyClass()
{
self = this;
}

MyClass::~MyClass()
{
self = 0;
}
 

dynamic.dll
Код:
// dynamic dll

///////////////////////////////////////////////////
dynamic.h
///////////////////////////////////////////////////
#ifndef DYNAMIC_H
#define DYNAMIC_H

#include <QObject>
#include "static.h"


class dynamic : public dyn_interface
{
public:
dynamic();
~dynamic();

public:
MyClass** pself();

};

#endif // DYNAMIC_H


///////////////////////////////////////////////////
dynamic.cpp
///////////////////////////////////////////////////
#include "dynamic.h"

dynamic::dynamic()
{

}

dynamic::~dynamic()
{

}

MyClass** dynamic::pself()
{
return &MyClass::self;
}



extern "C" Q_DECL_EXPORT dynamic* createObject()
{
return new dynamic;
}


exe.exe
Код:
///////////////////////////////////////////////////
main.cpp
///////////////////////////////////////////////////
#include <QtGui>
#include <static.h>


int main(int argc, char *argv[])
{
QApplication a(argc, argv);

MyClass* stat_obj = new MyClass;

QTextBrowser browser;

typedef dyn_interface* (*proto)();
QLibrary lib("dynamic");

proto func = (proto) lib.resolve("createObject");

dyn_interface* obj = func();

MyClass** pSelf = obj->pself();

QString text;
text = QString(
"in exe:<br>&MyClass::self=%1<br>MyClass::self=%2<br><br>"
"in dll pself:<br>&MyClass::self=%3<br>MyClass::self=%4<br><br>")
.arg((quint32)&MyClass::self,8,16)
.arg((quint32)MyClass::self,8,16)
.arg((quint32)pSelf,8,16)
.arg((quint32)*pSelf,8,16);

browser.insertHtml(text);
browser.show();

return a.exec();
}


выход:

in exe:
&MyClass::self= 40a008
MyClass::self= 3eece0

in dll pself:
&MyClass::self= 4c6048
MyClass::self= abcdef
« Последнее редактирование: Ноябрь 20, 2009, 12:42 от jasf » Записан
jasf
Гость
« Ответ #10 : Ноябрь 20, 2009, 13:12 »

Прошу прощения, разобрался. Помогло сделать static.dll - динамической. т.е. не shared_lib. Ошибка возникла из-за опыта работы с symbianом. Там shared lib является dllкой, и обращаться к функциям shared lib можно лишь при наличии .lib файла. Ну и такого поведения, как под windows (относительно памяти) - нет.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Ноябрь 20, 2009, 13:48 »

Ну вот, другое дело, все ясно
in exe:
&MyClass::self= 40a008
MyClass::self= 3eece0

in dll pself:
&MyClass::self= 4c6048
MyClass::self= abcdef
По-моему, это правильный и ожидаемый результат. Если Вы линковали статически, то у Вас и есть 2 MyClass - один в exe, другой в dll и они просто 2 разных, никак не связаны и MyClass::self у каждого свой. Для того что в exe Вы создали экземпляр, его self заполнился. Но для того что в dll Вы экземпляр не создавали - ну он и имеет "abcdef". Если планируете общий MyClass - в dll его (как Вы и сделали)
« Последнее редактирование: Ноябрь 20, 2009, 13:55 от Igors » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.05 секунд. Запросов: 23.