It seems setParent will cause crash
-
Hi,
Recently, I meet a very strange problem.
I am using Qt5.12 on windows10 with VS2017my code is:
HttpClient.h#ifndef HTTPCLIENT_H #define HTTPCLIENT_H #include <QObject> #include <QNetworkAccessManager> #include <QNetworkReply> class HttpClient : public QObject { Q_OBJECT protected: QNetworkAccessManager* m_networkManager = nullptr; QNetworkReply* m_reply = nullptr; public: explicit HttpClient(QObject *parent = nullptr); virtual ~HttpClient(); inline QNetworkReply* reply() const {return m_reply;} void start(); signals: void finished(); }; #endif // HTTPCLIENT_H
HttpClient.cpp
#include "HttpClient.h" #include "NetworkAccessManager.h" #include <QDebug> HttpClient::HttpClient(QObject *parent) : QObject(parent) { } HttpClient::~HttpClient() { #ifdef QT_DEBUG qDebug() << __FUNCTION__; #endif //// when use m_networkManager = new NetworkAccessManager(); // if (m_networkManager) { // m_networkManager->deleteLater(); // } } void HttpClient::start() { #ifdef QT_DEBUG qDebug() << __FUNCTION__; #endif { if (!m_networkManager) { // without "this" as parent, delete m_networkManager in destructor will not crash //m_networkManager = new NetworkAccessManager(); // with "this" as parent, not delete m_networkManager in destructor will crash m_networkManager = new NetworkAccessManager(this); } QNetworkRequest request(QUrl("https://qt.io/")); m_reply = m_networkManager->get(request); // with "this" as parent, not delete m_networkManager in destructor, not setParent(m_reply), // delete HttpClient after finished() signal will not crash setParent(m_reply); connect(m_reply, &QNetworkReply::finished, this, &HttpClient::finished); } }
call
{ HttpClient* client = new HttpClient; connect(client, &HttpClient::finished, this, [this, client](){ qDebug() << __FUNCTION__ << __LINE__; auto reply = client->reply(); //client->deleteLater(); reply->deleteLater(); }); client->start(); }
after calling
m_networkManager = new NetworkAccessManager(this);
, the m_networkManager will be a child of this(HttpClient), Then after callingsetParent(m_reply);
the HttpClient wiil be a child of reply, after the reply is finished, I calledreply->deleteLater();
, this should delete the three object one by one, but it will cause crash. If I do not use HttpClient as parent of the m_networkManager OR not usesetParent(m_reply);
then delete the m_networkManager in the destructor, it will not crash.Is there anyone know why did this happened? Thank you.
-
@Mozzie said in It seems setParent will cause crash:
Is there anyone know why did this happened? Thank you.
You create a circular dependency HttpClient -> NetworkAccessManager -> QNetworkReply.
But what do you try to achieve with this really bogus setParent() - call?
-
Hi,
Recently, I meet a very strange problem.
I am using Qt5.12 on windows10 with VS2017my code is:
HttpClient.h#ifndef HTTPCLIENT_H #define HTTPCLIENT_H #include <QObject> #include <QNetworkAccessManager> #include <QNetworkReply> class HttpClient : public QObject { Q_OBJECT protected: QNetworkAccessManager* m_networkManager = nullptr; QNetworkReply* m_reply = nullptr; public: explicit HttpClient(QObject *parent = nullptr); virtual ~HttpClient(); inline QNetworkReply* reply() const {return m_reply;} void start(); signals: void finished(); }; #endif // HTTPCLIENT_H
HttpClient.cpp
#include "HttpClient.h" #include "NetworkAccessManager.h" #include <QDebug> HttpClient::HttpClient(QObject *parent) : QObject(parent) { } HttpClient::~HttpClient() { #ifdef QT_DEBUG qDebug() << __FUNCTION__; #endif //// when use m_networkManager = new NetworkAccessManager(); // if (m_networkManager) { // m_networkManager->deleteLater(); // } } void HttpClient::start() { #ifdef QT_DEBUG qDebug() << __FUNCTION__; #endif { if (!m_networkManager) { // without "this" as parent, delete m_networkManager in destructor will not crash //m_networkManager = new NetworkAccessManager(); // with "this" as parent, not delete m_networkManager in destructor will crash m_networkManager = new NetworkAccessManager(this); } QNetworkRequest request(QUrl("https://qt.io/")); m_reply = m_networkManager->get(request); // with "this" as parent, not delete m_networkManager in destructor, not setParent(m_reply), // delete HttpClient after finished() signal will not crash setParent(m_reply); connect(m_reply, &QNetworkReply::finished, this, &HttpClient::finished); } }
call
{ HttpClient* client = new HttpClient; connect(client, &HttpClient::finished, this, [this, client](){ qDebug() << __FUNCTION__ << __LINE__; auto reply = client->reply(); //client->deleteLater(); reply->deleteLater(); }); client->start(); }
after calling
m_networkManager = new NetworkAccessManager(this);
, the m_networkManager will be a child of this(HttpClient), Then after callingsetParent(m_reply);
the HttpClient wiil be a child of reply, after the reply is finished, I calledreply->deleteLater();
, this should delete the three object one by one, but it will cause crash. If I do not use HttpClient as parent of the m_networkManager OR not usesetParent(m_reply);
then delete the m_networkManager in the destructor, it will not crash.Is there anyone know why did this happened? Thank you.
@Mozzie said in It seems setParent will cause crash:
HttpClient
Why should HttpClient be child of the reply?
This sounds wrong. -
@Mozzie said in It seems setParent will cause crash:
Is there anyone know why did this happened? Thank you.
You create a circular dependency HttpClient -> NetworkAccessManager -> QNetworkReply.
But what do you try to achieve with this really bogus setParent() - call?
Thank you. I want to delete the HttpClient object automatically after the QNetworkReply called deleteLater()
-
@Mozzie said in It seems setParent will cause crash:
HttpClient
Why should HttpClient be child of the reply?
This sounds wrong. -
Then connect deleteLater() to QNetworkReply::destroyed()
-
Then connect deleteLater() to QNetworkReply::destroyed()
@Christian-Ehrlicher
Thank you very much.