我正在尝试编写SingleApplication类,该类仅允许运行该程序的一个实例。我正在使用QSharedMemory实现

该程序可以正常工作,除非我使用值为"42"的键。我在做错什么吗?这是未定义的行为吗?

Main.cpp

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

    //QApplication a(argc, argv);
    SingleApplication a(argc, argv, "42"); //Does not work with '42'. Will work for any other value.



    MainWindow w;
    w.show();


    return a.exec();
}

SingleApplication.h
class SingleApplication : public QApplication
{
    Q_OBJECT

public:
    SingleApplication(int &argc, char *argv[], const QString uniqueKey);

    bool alreadyExists() const{ return bAlreadyExists; }

    bool isMasterApp() const { return !alreadyExists(); }

    bool sendMessage(const QString &message);

public slots:
    //void checkForMessages();

signals:
    //void messageAvailable(const QStringList& messages);

private:
    bool bAlreadyExists;
    QSharedMemory sharedMemory;

};

SingleApplication.cpp
SingleApplication::SingleApplication(int &argc, char *argv[], const QString uniqueKey) : QApplication(argc, argv){

    sharedMemory.setKey(uniqueKey);

    //Create if one does not exist already
    if(sharedMemory.create(5000))
    {
        qDebug() << "Created!";

        bAlreadyExists = false;
    }
    else{
        if(sharedMemory.error() == QSharedMemory::AlreadyExists){
            qWarning() << "Program is already running!";
        }
    }
}

最佳答案

我为您提出下一个解决方案。它已经过测试,但是不支持在实例之间发送消息。并且它解决了您的解决方案中的一些错误。因为仅测试内存还不够。您需要保护共享内存的创建。

RunGuard.h

#ifndef RUNGUARD_H
#define RUNGUARD_H

#include <QObject>
#include <QSharedMemory>
#include <QSystemSemaphore>


class RunGuard
{

public:
    RunGuard( const QString& key );
    ~RunGuard();

    bool isAnotherRunning();
    bool tryToRun();
    void release();

private:
    const QString key;
    const QString memLockKey;
    const QString sharedmemKey;

    QSharedMemory sharedMem;
    QSystemSemaphore memLock;

    Q_DISABLE_COPY( RunGuard )
};


#endif // RUNGUARD_H

RunGuard.cpp
#include "RunGuard.h"

#include <QCryptographicHash>


namespace
{

QString generateKeyHash( const QString& key, const QString& salt )
{
    QByteArray data;

    data.append( key.toUtf8() );
    data.append( salt.toUtf8() );
    data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex();

    return data;
}

}


RunGuard::RunGuard( const QString& key )
    : key( key )
    , memLockKey( generateKeyHash( key, "_memLockKey" ) )
    , sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) )
    , sharedMem( sharedmemKey )
    , memLock( memLockKey, 1 )
{
        QSharedMemory fix( sharedmemKey );    // Fix for *nix: http://habrahabr.ru/post/173281/
        fix.attach();
}

RunGuard::~RunGuard()
{
    release();
}

bool RunGuard::isAnotherRunning()
{
    if ( sharedMem.isAttached() )
        return false;

    memLock.acquire();
    const bool isRunning = sharedMem.attach();
    if ( isRunning )
        sharedMem.detach();
    memLock.release();

    return isRunning;
}

bool RunGuard::tryToRun()
{
    if ( isAnotherRunning() )   // Extra check
        return false;

    memLock.acquire();
    const bool result = sharedMem.create( sizeof( quint64 ) );
    memLock.release();
    if ( !result )
    {
        release();
        return false;
    }

    return true;
}

void RunGuard::release()
{
    memLock.acquire();
    if ( sharedMem.isAttached() )
        sharedMem.detach();
    memLock.release();
}

关于c++ - QSharedMemory::create()问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26704533/

10-11 15:53