Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Alp от Август 25, 2009, 19:35



Название: QFontDatabase app crash
Отправлено: Alp от Август 25, 2009, 19:35
Есть менеджер шрифтов, реализованный как синглтон Мейерса. В нем используется QFontDatabase что бы подгрузить шрифты с диска (точнее, из ресурсов), операция проходит успешно, вызов вида
id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-Bold.otf")
возвращает id загруженного шрифта, он != -1.

В деструкторе вызывается QFontDatabase::removeAllApplicationFonts(), и в нём приложение падает. Если этот вызов закомментировать - всё в порядке.
Помогите понять, в чем проблема.

Да, если вызов removeAllApplicationFonts переместить из в конструктор, сразу же после загрузки шрифтов - проблема исчезает, даже если вызов в деструкторе оставить.

Код
C++ (Qt)
#define SINGLETON_COPY_CREATE_RESTRICT(ClassName) \
                               ClassName() {}  \
                               ClassName(const ClassName&) {}  \
                               ClassName& operator=(const ClassName&) {return *(new ClassName());}   \
                               friend class Singleton <ClassName>;
 
#define SINGLETON_COPY_RESTRICT(ClassName)  ClassName(const ClassName&) {}  \
                                           ClassName& operator=(const ClassName&) {return *(new ClassName());}   \
                                           friend class Singleton <ClassName>;
 
template<class T> class Singleton   //Single-threaded Meyers singleton
{
protected:
   Singleton()                             {}
   Singleton(const Singleton&)             {}
   Singleton& operator=(const Singleton&)  {}
   virtual ~Singleton()                    {}
 
public:
   static T& Instance()
   {
       static T object;
       return object;
   }
};
 

Код
C++ (Qt)
class FontManager : public Singleton<FontManager>
{
   SINGLETON_COPY_RESTRICT(FontManager)
   FontManager();
public:
   ~FontManager();
 
};
 

Код
C++ (Qt)
FontManager::FontManager(void)
{
   int id = -1;
   id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-Bold.otf");
   id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-BoldCond.otf");
   id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-BoldIt.otf");
   id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-Cond.otf");
   id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-It.otf");
   id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-Regular.otf");
   id = QFontDatabase::addApplicationFont(":/fonts/MyriadPro-CondIt.otf");
}
 
FontManager::~FontManager()
{
   QFontDatabase::removeAllApplicationFonts();    //AARRRRRGHHHH!
}
 
 



Название: Re: QFontDatabase app crash
Отправлено: BRE от Август 25, 2009, 20:30
Сейчас нет времени разбираться досконально, но есть предположение:
Вопрос в порядке вызова деструкторов для статических объектов. Возможно в момент вызова деструктора FontManager и соответственно метода QFontDatabase::removeAllApplicationFonts() внутренний структуры QFontDatabase уже разрушены.
То, что проблема исчезает если нет ни одного загруженного фонта, то это возможно из-за следующего кода в removeAllApplicationFonts():
Код
C++ (Qt)
   QMutexLocker locker(fontDatabaseMutex());
 
   QFontDatabasePrivate *db = privateDb();
   if (db->applicationFonts.isEmpty()) // !!! выходим без выгрузки фонтов
       return false;
 
   // Если фонты есть - думаю падает где-то здесь...
   FcConfigAppFontClear(0);
   db->applicationFonts.clear();
   db->invalidate(); // <<< Здесь очищается кэш фонтов (думаю здесь)
   return true;