Пул экземпляров QObject

У меня проблема, я не уверен, как решить ..

У нас есть общий пул объектов. Когда объект запрашивается, пул возвращается QSharedPointer к первому доступному экземпляру, с указанием пользовательского Deleter. Удалитель просто возвращает объект в пул, когда QSharedPointer Счетчик экземпляров равен 0.
Все отлично работает для простых объектов. Это также отлично работает для QObject преемники, при компиляции в Qt 5.

Однако, если скомпилировано в Qt 4.6 — начинаются проблемы: когда один и тот же объект запрашивается второй раз — приложение завершает работу с ошибкой:

«QSharedPointer: указатель ххх уже имеет подсчет ссылок»

Я написал простой тест:

QObject* obj = new QObject();
QSharedPointer<QObject> p(obj, deleter); // deleter here does nothing
p.clear();
QSharedPointer<QObject> p2(obj, deleter); // this crashes the app

И, конечно же, это терпит неудачу при компиляции в Qt 4.6. Опять же: отлично работает в QT 5.x.

Изучив исходный код Qt, он обнаружил, что 4.6 инициализирует внутренний счетчик ссылок в QObject когда это QObject используется как QSharedPointer параметр. Это сделано для того, чтобы никакие два умных указателя не могли указывать на один и тот же объект, и он будет сброшен только в деструкторе.

Qt5 не проверяет значение счетчика реф, когда QObject Экземпляр обернут в смарт-указатель, таким образом, он работает.

Кто-нибудь знает обходной путь для более старой версии Qt? Есть ли способ полностью сбросить внутреннее состояние Qt, включая счетчик ссылок? Любые намеки приветствуются.

4

Решение

Предполагая, что у вас есть пул, чтобы избежать выделения и освобождения памяти, вы должны выделить память только один раз, а затем явно вызывать конструктор и деструктор, когда вы запрашиваете и возвращаете «новый» объект.

/* deleter calls destructor explicitly when return object to pool */
void deleter(QObject *object) {
object->~QObject();
mark_as_available();
}

/* allocate (one object) pool memory without calling constructor*/
QObject *object = ::operator new(sizeof(QObject));

/* request object - calling constructor on already allocated memory */
mark_as_taken();
return QSharedPointer(::new (object) QObject, &deleter);

/* deallocate pool memory without calling destructor */
::operator delete(object);
0

Другие решения

вам разрешено создавать только один раз QSharedPointer от QObject
последний вам нужно будет скопировать существующий QSharedPointer пример

в соответствии с Qt 4 и 5 документы:

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

так что ваши образцы поведения, как показано ниже:

QObject* obj = new QObject();
QSharedPointer<QObject> p(obj, deleter); // deleter here does attach to "obj"p.clear(); //this does cause delete of "obj"QSharedPointer<QObject> p2(obj, deleter); // using deleted pointer will cause crash (if you are lucky XD)

с помощью QWeakPointer не удалит QObject и утверждение:

«QSharedPointer: указатель ххх уже имеет подсчет ссылок»

чтобы убедиться, что вы не создали несколько случайных удалений (что сделало мой день безопасным, я использовал QSharedPointer но имел ввиду QWeakPointer) но иногда это мешает.

0

По вопросам рекламы [email protected]