3

私は本当に困惑しており、誰かが私の問題について何か知っていることを願っています.

非常に単純な SSL クライアントとサーバーがあります。接続は問題ありません。通信は問題ありません。この問題は、クライアントがサーバーから切断されたときに発生します。これにより、 SLOT で処理されるサーバー上でシグナルが発生しますerror_handler(QAbstractSocket::SocketError in_error)。その関数では、sslSocketオブジェクトを削除する必要があると思います。

ただし、これを行うと、サーバーでセグメント フォールトが発生します。何が起こっているのかわかりません。これは本当に簡単だと思っていましたが、どうやらQt(またはその他)の概念が欠けているようです。

誰でも助けてもらえますか?

重要なサーバー コード:

void SSLServer::incomingConnection(int sd)
{
    sslSocket = new SSLSocket(this);
    if( sslSocket->setSocketDescriptor(sd))
    {
        QFile sslkeyfile(privKey_);
        sslSocket->setPrivateKey(QSslKey(sslkeyfile.readAll(),QSsl::Rsa));

        QFile cliCertFile(serverCert_);
        sslSocket->setLocalCertificate(QSslCertificate(cliCertFile.readAll()));

        QFile certFile(caCert_);
        sslSocket->addCaCertificate(QSslCertificate(certFile.readAll()));

        sslSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
        sslSocket->setProtocol(QSsl::SslV3);

        connect(sslSocket, SIGNAL(error(QAbstractSocket::SocketError)),
                this, SLOT(error_handler(QAbstractSocket::SocketError)));
        connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
                this, SLOT(ssl_error_handler(QList<QSslError>)));
        connect(sslSocket, SIGNAL(encrypted()), this,
                SLOT(ready()));
        connect(sslSocket, SIGNAL(readyRead()), this,
                SLOT(read_data_from_client()));

        sslSocket->startServerEncryption();
        if(!sslSocket->waitForEncrypted())
        {
            qDebug() << "failed to perform SSL handshake with client";
            return;
        }
    }

}

void SSLServer::read_data_from_client()
{
    QByteArray qstrbytes = sslSocket->readAll();
    qDebug() << Q_FUNC_INFO << qstrbytes;
}

void SSLServer::ready()
{
    QSslCertificate clientCert = sslSocket->peerCertificate();
    qDebug() << clientCert.isValid();
}

void SSLServer::error_handler(QAbstractSocket::SocketError in_error)
{
    qDebug() << Q_FUNC_INFO << in_error;
    if(in_error == QAbstractSocket::RemoteHostClosedError)
    {
        delete sslSocket; //// line causes crash !!!!!!
    }
}
4

4 に答える 4

2

SSLSocket クラスなどの QObject クラスがどのように記述されるかを考えると、次のようになります。

class SSLSocket : public QObject
{        
   signals:
        void sslErrors(QList<QSslError>);

     void SomeFunction()
     {
        // something went wrong, emit error
        emit sslErrors(errorList);

        Cleanup(); // If a slot connected to sslErrors deleted this, what happens now?!
     }
}

シグナル sslErrors がトリガーされると、スロット関数が呼び出されます。ご覧のとおり、シグナルを発行した後、クラスにはさらに多くの作業が必要になる場合があります。スロット内のオブジェクトをすぐに削除するとクラッシュするため、スロット関数で QObject インスタンスを削除するには常に deleteLater() を使用する必要があります。

deleteLater 関数は、スロット関数の実行が完了し、コール スタックが復元されたことを確認するため、適切なタイミングで削除されます。

上記のコードは実際に SSLSocket が行うものではなく、単なる例であることに注意してください。

于 2013-08-28T10:01:12.670 に答える
1

QSslSocket を使用した Qt のサンプル コードは次のとおりです。

http://qt-project.org/doc/qt-4.8/network-securesocketclient-sslclient-cpp.html

他のポスターが述べたように、を使用deleteLater()してください。エラー通知だけがそうする場所ではありません。

于 2013-08-27T17:50:06.153 に答える