C ++ Singleton создается дважды - проблема со статической переменной-членом - PullRequest
0 голосов
/ 19 ноября 2018

Я реализовал стандартный шаблон синглтона (версия без резьбы) следующим образом:

HPP:

#ifndef SERVICEMANAGER_H
#define SERVICEMANAGER_H

#include <QObject>
#include <QVariant>
#include <QMap>
#include "IService.h"
#include "qhcore_global.h"
#include <QDebug>



class  ServiceManager : public QObject
{
    Q_OBJECT

public:
    static ServiceManager*     instance();
    ~ServiceManager(){qDebug()<<Q_FUNC_INFO;}
    IService*           service(QString name);
    bool                registerService(IService* service);

private:
    explicit            ServiceManager(QObject *parent = nullptr);

    QMap<QString, IService*>    _serviceMap;
    static ServiceManager*      __instance;

signals:
    void serviceAdded(QString serviceName);
public slots:
};



#endif // SERVICEMANAGER_H

касты:

ServiceManager* ServiceManager::__instance = nullptr;

ServiceManager::ServiceManager(QObject *parent) : QObject(parent)
{
     qDebug()<<"CREATE::CTOR";
}

ServiceManager* ServiceManager::instance()
{
    qDebug()<< __instance << "BEFORE";
    if(__instance == nullptr)
    {
        qDebug()<<"CREATE";
        __instance = new ServiceManager();
        qDebug()<< __instance << "AFTER";
    }
    return __instance;
}

и мой журнал выглядит так

[DEBUG    17.11. - 17:50:18:748] --
[DEBUG    17.11. - 17:50:18:748] -- QObject(0x0) BEFORE
[DEBUG    17.11. - 17:50:18:748] -- CREATE
[DEBUG    17.11. - 17:50:18:748] -- CREATE::CTOR
[DEBUG    17.11. - 17:50:18:748] -- ServiceManager(0x55e9fc6fb510) AFTER
[DEBUG    17.11. - 17:50:18:748] -- 0
[INFO     17.11. - 17:50:18:748] -- "Service registered: lab"
[DEBUG    17.11. - 17:50:18:748] -- 1
[INFO     17.11. - 17:50:18:749] -- "Added Resource factory for synclist for descriptor: labcontrol/logs"
[INFO     17.11. - 17:50:18:749] -- "Added Resource factory for synclist for descriptor: labcontrol/users"
[INFO     17.11. - 17:50:18:749] -- "Added Resource factory for synclist for descriptor: labcontrol/permissions"
[INFO     17.11. - 17:50:18:749] -- "Added Resource factory for synclist for descriptor: labcontrol/cards"
[INFO     17.11. - 17:50:43:973] -- "::ffff:192.168.1.32"  has connected.
[INFO     17.11. - 17:50:43:985] -- "admin logged in. (" 1  sessions open)
[INFO     17.11. - 17:50:43:985] -- Device registered:  "4f2o4o7b1a1r"
[INFO     17.11. - 17:50:44:003] -- Create ListResource with FS Resource Handler "logger/mappings_synclist"
[INFO     17.11. - 17:50:44:005] -- Create ListResource with FS Resource Handler "labcontrol/logs_synclist"
[INFO     17.11. - 17:50:44:007] -- Create ListResource with FS Resource Handler "labcontrol/users_synclist"
[INFO     17.11. - 17:50:44:009] -- Create ListResource with FS Resource Handler "labcontrol/permissions_synclist"
[INFO     17.11. - 17:50:44:011] -- Create ListResource with FS Resource Handler "labcontrol/cards_synclist"
[DEBUG    17.11. - 17:50:45:136] -- QObject(0x0) BEFORE
[DEBUG    17.11. - 17:50:45:136] -- CREATE
[DEBUG    17.11. - 17:50:45:136] -- CREATE::CTOR
[DEBUG    17.11. - 17:50:45:137] -- ServiceManager(0x55e9fc749340) AFTER
[DEBUG    17.11. - 17:50:45:137] --  COUNT: 0
[DEBUG    17.11. - 17:50:45:137] -- ()
[WARNING  17.11. - 17:50:45:138] -- "Unavailable servcie: lab"

В журнале видно, что экземпляр синглтона будет создан дважды. Во второй раз, когда я вызываю функцию instance (), закрытый статический член __instance снова содержит nullptr. Это совершенно странно. Тот же код отлично работает на других машинах с разными платформами (OSx, Raspbian, ...).

Моя система представляет собой beelink BT3 pro, на котором работает Ubuntu Server 18.10, x64. Сам код представляет собой облако IoT на основе WebSocket, которое использует Qt5 в сочетании с плагинами.

Что я пробовал:

с использованием различных компиляторов, таких как gcc-8, gcc-7 и gcc-6. Собираю Qt самостоятельно, чтобы все двоичные файлы были собраны с одним и тем же компилятором.

Опять же: Мое приложение использует плагины. Вероятно, это связано с тем, что синглтон-объект используется в разных плагинах, загружаемых во время выполнения из общих объектных файлов через QPluginLoader.

edit: я не использую потоки и не использую разные пространства имен.

Любая подсказка приветствуется! Заранее спасибо!

РЕДАКТИРОВАТЬ2 (РЕШЕНИЕ) :

(перешел к моему ответу ниже.)

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

Вы должны использовать макрос Q_GLOBAL_STATIC () для совместного использования экземпляра между плагинами.Файл cpp можно переписать так:

   Q_GLOBAL_STATIC(ServiceManager, myServiceManagerInstance)

    ServiceManager *ServiceManager::instance()
    {
            return myServiceManagerInstance();
    }
0 голосов
/ 20 ноября 2018

К сожалению, ответы раньше не работали ... Все та же проблема.НО .. Я обнаружил проблему:

В моем приложении есть пара независимых плагинов и основной плагин.Последний из них: плагин и общая библиотека для всех остальных плагинов.У моего приложения есть относительный путь поиска, где он ищет плагины для загрузки.Все идет нормально.Но независимые плагины расширения должны найти основной плагин для ссылки во время выполнения.Поэтому я скопировал основной плагин в / usr / lib.Это была проблема.Было две копии libCorePlugin.so - одна в папке плагина, а другая в / usr / lib.Я не знаю, почему это сработало на всех других машинах ... Но пусть LD_LIBRARY_PATH указывает на общую папку плагина, а не копирует файл в / usr / lib, чтобы решить проблему.

Кто-нибудь имеет представление, почему это работало на некоторых системах раньше?

0 голосов
/ 19 ноября 2018

Если вы статически связываете ServiceManager.cpp (или ServiceManager.o) с несколькими динамическими библиотеками, каждая из них может в конечном итоге содержать свой собственный экземпляр ServiceManager::__instance.

. Решение для этого будетпоместите ServiceManager.o в отдельную динамическую библиотеку, доступную для всех ваших библиотек "плагинов".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...