QTcpSocket指针在视图中生成SIGSEGV。 (QT5)

时间:2018-09-30 15:31:46

标签: c++ qt pointers qt5 sigsegv

嗨,

当我想使用带有以下代码的QTcpSocket时,我得到了SIGSEGV。 (底部有更多说明)


用于创建QTTCPSocket(将保留QTcpSocket指针)的函数:

std::shared_ptr<QTTCPSocket> createQtSocket(std::string host, unsigned int port)
{
    QTcpSocket *sock = new QTcpSocket;
    sock->connectToHost(QHostAddress(QString::fromStdString(host)), port);
    if (!sock->waitForConnected())
        throw std::runtime_error("Connection refused");
    return std::make_shared<QTTCPSocket>(sock);
}

QTTCPSocket类:

class QTTCPSocket {
public:
    QTTCPSocket(QTcpSocket *socket)
        : _socket(socket)
    {};

    ~QTTCPSocket() = default;

    void send(const std::string &msg)
    {
        std::cout << msg << std::endl;
        _socket->write(&msg[0], static_cast<qint64>(msg.length())); // produces a SIGSEGV if called from a qt event (a button for example)
        _socket->waitForBytesWritten(0);
    }

private:
    QTcpSocket *_socket;
};

主要功能:

int main()
{
    std::shared_ptr<QTTCPSocket> socket = createQtSocket("127.0.0.1", 33333);
    ViewStateMachine vsm(socket);
    vsm.init();
    vsm.start();
}

ViewStateMachine类(hpp):

class ViewStateMachine {
public:
    ViewStateMachine(std::shared_ptr<QTTCPSocket> sock);
    void init();
    void start();
    std::shared_ptr<QTTCPSocket> getSock();
private:
    LoginView *_loginView;
    std::shared_ptr<QTTCPSocket> _sock;
};

ViewStateMachine类(cpp):

#include "ViewStateMachine.hpp"

ViewStateMachine::ViewStateMachine(std::shared_ptr<QTTCPSocket> socket)
    : _sock(std::move(socket))
{
}

void ViewStateMachine::init()
{
    _loginView = new LoginView(this);
    _loginView->init();
}

void ViewStateMachine::start()
{
    _loginView->show();
}

std::shared_ptr<QTTCPSocket> ViewStateMachine::getSock()
{
    _sock->send("test1"); // SIGSEGV inside (check above) 
    return _sock; // if I remove _sock->send("test1"), it SIGSEGV in the shared_ptr's constructor (only if called from a qt event (a button for example)
}

LoginView是一个被动类,它通过QObject::connect(_connectBtn, SIGNAL(clicked()), this, SLOT(onClick_connectBtn()));的成员函数onClick_connectBtn()LoginView注册事件。


所有这些代码段可能会造成混淆,因此在这里进行逐步说明:

  1. main()开始:创建一个QTcpSocket *中包含的QTTCPSocket class中包含的std::shared_ptr<QTTCPSocket>
  2. 使用ViewStateMachine创建一个shared_ptr实例,该实例将存储在该实例中。我们将其称为vsm
  3. 调用vsm.init(),它将使用LoginViewthis)创建一个vsm实例。 LoginView将存储ViewStateMachine实例。
  4. 调用vsm.start(),它将调用_loginView.show()(来自QT的QWidget),它将显示登录视图。

一切正常,我们可以看到登录视图。

但是,如果我想在LoginView中使用我的套接字:  *当我想从_loginView->init()或在LoginView的构造函数中使用它时,它很好用!  *当我想从LoginView::onClick_connectBtn中使用它(由QT调用,也许在诸如构造函数之类的特殊环境中,不确定)时,它会产生SIGSEGV,我在上面的代码(shared_ptr的构造函数或来自QT'套接字)。

要从LoginView获取套接字,我使用ViewStateMachine::getSock()_viewStateMachine->getSock())。

Valgrind显示

pure virtual method called terminate called without an active exception

shared_ptr的构造函数使用互斥量递增值时会生成SIGSEGV。 当我使用_socket(QT'套接字)时,写SIGSEGV。指针地址从头到尾没有变化。

如果还有其他问题,请询问!

非常感谢您的帮助:)。

编辑:如果我用C指针替换每个std :: shared_ptr,它将起作用。

0 个答案:

没有答案