I have a class ‘Downloader’ derived from QObject that runs in a worker thread. When the thread is started, the downloader creates a QNetworkAccessManager object on the heap, and starts to request files. I keep track of how many files have been requested and received. Once I’ve gotten all of the files, I delete the QNetworkAccessManager object and exit the thread. My problem is that deleting the manager object causes a crash no matter when or where I do this. I’ve even tried manager->deleteLater(). If I don’t delete it, my code runs great, but I know there is a memory leak there. Here is a stripped down version of my code.
Creating the downloader and thread, and setting signals up so that starting the thread starts the downloads, and when the downloads are complete, the thread stops:
QThread thread;
Downloader downloader;
downloader.setFiles(files);
downloader.moveToThread(&thread);
downloader.connect(&thread, SIGNAL(started()), SLOT(downloadFiles()));
thread.connect(&downloader, SIGNAL(downloadsFinished()), SLOT(quit()));
thread.start();
Implementation for the downloader:
void Downloader::downloadFiles()
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));
receivedCount = 0;
requestCount = files.count();
for (QStringList::const_iterator pos = files.begin(); pos != files.end(); ++pos)
{
QUrl url(*pos);
manager->get(QNetworkRequest(url));
}
}
void Downloader::finished(QNetworkReply *reply)
{
// *** Get the file data and process it *** //
++receivedCount;
reply->deleteLater();
if (receivedCount == requestCount)
{
// manager->deleteLater();
emit downloadsFinished();
}
}
The commented out line will crash the app. Even deleting the manager in Downloader’s destructor, or setting the downloader as the manager’s parent will crash the app.
I first tried creating the manager as a regular member variable on the stack, but doing so causes errors of it’s own since the manager would be created in the GUI thread and later try to create children on a different thread.
And before anybody says “QNetworkAccessManager is asynchronous. Why use it in a worker thread?” I have my reasons. It shouldn’t be THAT unheard of to do something like this.
The only obvious problem is below but I am not sure if you have posted your entire code or not
You are creating a local
QNetworkAccessManager *managerin your method but not keeping a reference to it and then trying to access it within finished() method.You should assign
new QNetworkAccessManager();a member variable !