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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Статические классы в статической библиотеке ???  (Прочитано 8910 раз)
alex12
Гость
« : Август 13, 2009, 20:53 »

Недавно на форуме была ссылка на такой документ: http://qt.gitorious.org/qt/pages/CodingConventions

Там есть пункт про статические объекты, размещенные в статической библиотеке. Утверждается, что для них
может не вызываться конструктор класса и они предлагают использовать макрос Q_GLOBAL_STATIC.

У меня в проекте есть статический QString, выполняющий роль буфера вывода на служебную консоль.
Пока я никаких проблем не замечал. Простой тестовый пример на компиляторе MinGW показывает, что все
хорошо и конструктор вызывается. Тест с gcc в linux тоже проблемы не выявил.

Насколько обоснованны их опасения? Сталкивался ли кто с такой ситуацией?

Цитировать
Anything that has a constructor or needs to run code to be initialized cannot be used as global object in library code, since it is undefined when that constructor/code will be run (on first usage, on library load, before main() or not at all). Even if the execution time of the initializer is defined for shared libraries, you’ll get into trouble when moving that code in a plugin or if the library is compiled statically:
Код:
  // global scope
  static const QString x; // Wrong - default constructor needs to be run to initialize x  
  static const QString y = "Hello"; // Wrong - constructor that takes a const char * has to be run  
  QString z; // super wrong  
  static const int i = foo(); // wrong - call time of foo() undefined, might not be called at all  
Things you can do:
Код:
  // global scope
  static const char x[] = "someText"; // Works - no constructor must be run, x set at compile time  
  static int y = 7; // Works - y will be set at compile time  
  static MyStruct s = {1, 2, 3}; // Works - will be initialized statically, no code being run  
  static QString *ptr = 0; // Pointers to objects are ok - no code needed to be run to initialize ptr  


Use Q_GLOBAL_STATIC to create static global objects instead:
Код:
 
 Q_STATIC_GLOBAL(QString, s)

  void foo()  
  {  
      s()->append("moo");  
  }  


Note: Static objects in a scope are no problem, the constructor will be run the first time the scope is entered. The code is not reentrant, though.
« Последнее редактирование: Август 13, 2009, 21:01 от alex12 » Записан
SABROG
Гость
« Ответ #1 : Август 13, 2009, 21:27 »

Цитировать
Пока я никаких проблем не замечал.

Ну это не значит, что они не могут возникнуть. Проблема старая. http://faqs.org.ru/progr/c_cpp/cpp_lite3.htm

Чтобы она всплыла достаточно завести новый класс, который вынести в отдельный файл и использовать там эту статическую переменную. С вероятностью в 50% возникнет проблема. Один и тот же код может по-разному работать будучи собранным на разных компиляторах. Решение простое, прописать статическую переменную внутри метода/функции:

Код
C++ (Qt)
void foo()
{
   static const QString x;
   ...
}
 

Тогда объект будет создан в момент вызова этой функции и не будет необходимости гадать был ли выполнен конструктор до его использования или нет. Т.е. это не проблема Qt, это проблема всего C++. То, что работает сейчас - не показатель, надо сразу учиться писать программы правильно.
Записан
Winstrol
Гость
« Ответ #2 : Август 13, 2009, 21:33 »

Насколько обоснованны их опасения? Сталкивался ли кто с такой ситуацией?
Это qtэшная реализация шаблона singleton. В книге А.Александреску про него много понаписано для чего он нужен, в том числе и грабли статических объектов. Если кратко, то порядок инициализации статических объеков, объявленных в разных cpp файлах, не определен, поэтому объекты из разных модулей не могут зависеть друг от друга.
Записан
alex12
Гость
« Ответ #3 : Август 13, 2009, 21:41 »

Решение простое, прописать статическую переменную внутри метода/функции:
Код
C++ (Qt)
void foo()
{
 static const QString x;
 ...
}
 
Тогда объект будет создан в момент вызова этой функции...

Действительно, простое решение. Спасибо.
Записан
Winstrol
Гость
« Ответ #4 : Август 13, 2009, 21:45 »

Действительно, простое решение. Спасибо.
Простое, но не thread-safe.
Записан
ритт
Гость
« Ответ #5 : Август 13, 2009, 21:45 »

в случае с кустригом ничего страшного, наверное, не будет (не знаю, мб с кодеками какая возня случится из-за неверной последовательности), но в общем и целом предыдущие ораторы правы - в первую очередь Q_GLOBAL_STATIC нужен для выполнения контроля за временем жизни объекта - это и без чтения Александреску можно понять Улыбающийся
а вот для статического QSettings последовательность инициализации была бы уже критична. поэтому, слушай SABROG'а - пиши правильно изначально )
Записан
alex12
Гость
« Ответ #6 : Август 13, 2009, 22:05 »

Я с радостью начну использовать Q_GLOBAL_STATIC, но несколько смущает его статус "for internal use".
Записан
ритт
Гость
« Ответ #7 : Август 14, 2009, 01:45 »

и? это макрос - раз, не встречается в апи - два. т.е. реализацию могут изменить в любой момент. но об этом нет смысла беспокоиться.
Записан
SABROG
Гость
« Ответ #8 : Август 14, 2009, 08:13 »

Эмм, народ. http://qt.gitorious.org/qt/pages/CodingConventions написан не для пользователей Qt, а для разработчиков, которые будут коммитить свои патчи для Qt в git'e.
Записан
SASA
Гость
« Ответ #9 : Август 20, 2009, 12:20 »

Можно создать класс, и у него статический член.
Цитировать
Note: Static objects in a scope are no problem, the constructor will be run the first time the scope is entered.
Использую не только  QString, всё прикрасно работает.
Была проблема в Linux использования статических данных в статических библиотеках. Если подлинковывать её в несколько длл, которые подгружаются в один исполняемый файл, то при завершении программы каждая длл пытается удалить эти данные. Ну и на второй попытке прога падает. Как это обойти не понял, поэтому из статической библиотеки сделал динамическую.
Может кто подскажет другой путь.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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