PDA

View Full Version : a segmentation fault



yaohao@qtcentre
15th March 2011, 12:48
I was beaten by a segmentation fault,
following is my source code



void PieceThread::slotReadReady()
{
while(reply!=NULL&&!pauseFlag&&!reply->atEnd())
{
QMutexLocker locker(&mutex);
file->seek(workingPos);
workingPos+=file->write(reply->read(4096)); //segmentation fault happend here!
emit this->signalProgressIncrease(workingPos-oldWorkingPos);
oldWorkingPos=workingPos;
}
}


I promise that the "file" and the "reply" are legal pointer,

following is the Call Stack Window

0 QList<QNetworkReplyImplPrivate::InternalNotifications>::contains qlist.h 864 0x680cd407
1 QNetworkReplyImplPrivate::backendNotify qnetworkreplyimpl.cpp 365 0x68048179
2 QNetworkReplyImpl::readData qnetworkreplyimpl.cpp 873 0x6804a2f8
3 QIODevice::read qiodevice.cpp 829 0x6a1ab817
4 QIODevice::read qiodevice.cpp 964 0x6a1abd3b //here is the "read(4096)"
5 PieceThread::slotReadReady piecethread.cpp 48 0x4048e3
6 PieceThread::qt_metacall moc_piecethread.cpp 84 0x408a73
7 QMetaObject::metacall qmetaobject.cpp 237 0x6a2060b0
8 QMetaCallEvent::placeMetaCall qobject.cpp 535 0x6a210d55
9 QObject::event qobject.cpp 1217 0x6a212c60
10 QApplicationPrivate::notify_helper qapplication.cpp 4462 0x7ebde0
11 QApplication::notify qapplication.cpp 3862 0x7e9732
12 QCoreApplication::notifyInternal qcoreapplication.cpp 731 0x6a2015f8
13 QCoreApplication::sendEvent qcoreapplication.h 215 0x6a268308
14 QCoreApplicationPrivate::sendPostedEvents qcoreapplication.cpp 1372 0x6a2026a3
15 qt_internal_proc qeventdispatcher_win.cpp 497 0x6a22499f
16 USER32!GetDC C:\WINDOWS\system32\user32.dll 0 0x77d18734
17 ?? 0 0x3301a4
18 ?? 0 0x401
19 ?? 0

the line 0's call stack source code is from "qlist.h"



Q_OUTOFLINE_TEMPLATE QBool QList<T>::contains(const T &t) const
{
Node *b = reinterpret_cast<Node *>(p.begin());
Node *i = reinterpret_cast<Node *>(p.end());
while (i-- != b)
if (i->t() == t) //segmentation fault happend here
return QBool(true);
return QBool(false);
}


http://www.qtcn.org/bbs/attachment/Mon_1103/17_109564_8187bed6c057076.jpg


thank you for helping me!

MarekR22
15th March 2011, 13:30
I'm pretty sure that something is wrong with slots. Note that PieceThread::slotReadReady() will be called from main thread, since PieceThread belongs to this tread (probably)!
But don't move PieceThread to himself (this is big mistake).
This is mainly guessing because we don't see enough details.

Everything what you what to do in separate thread and should react on signals from other threads (emit signals to other threads) move to own QObject. Then create QThread for it and QObject::moveToThread.
See this useful article (http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/).

yaohao@qtcentre
16th March 2011, 03:45
thank for your help!

following is the detail code,
slotReadReady() will be called from subclass QThread



#include"piecethread.h"
#include<QtNetwork>
#include <QtGui>
#include"mission.h"

PieceThread::PieceThread(QObject *parent, short thn, quint64 bp, quint64 ep, QUrl u, QFile *f):
QThread(parent),threadNumber(thn),beginPos(bp),end Pos(ep),url(u),file(f)
{

qnam=NULL;
oldWorkingPos=workingPos=beginPos;
pauseFlag=false;
reply=NULL;
}

void PieceThread::run()
{
startTheThread();
}

QNetworkRequest PieceThread::setupTheRequest()
{
QNetworkRequest request(url);
QByteArray range=QByteArray("bytes=")+
QByteArray::number(beginPos)+
QByteArray("-")+
QByteArray::number(endPos);
request.setRawHeader("RANGE",range);
return request;
}

void PieceThread::startTheThread()
{
QNetworkRequest request=setupTheRequest();
qnam=new QNetworkAccessManager;
reply=qnam->get(request);
connect(reply,SIGNAL(readyRead()),this,SLOT(slotRe adReady()));
connect(reply,SIGNAL(finished()),this,SLOT(slotFin ished()));

this->exec();
}

void PieceThread::slotReadReady()
{
while(reply!=NULL&&!pauseFlag&&!reply->atEnd())
{
QMutexLocker locker(&mutex);
file->seek(workingPos);
workingPos+=file->write(reply->read(4096));
emit this->signalProgressIncrease(workingPos-oldWorkingPos);
oldWorkingPos=workingPos;
}
}

void PieceThread::slotFinished()
{

disconnect(reply,SIGNAL(readyRead()),this,SLOT(slo tReadReady()));
disconnect(reply,SIGNAL(finished()),this,SLOT(slot Finished()));
reply->deleteLater();
reply=NULL;
qnam->deleteLater();
qnam=NULL;
if(pauseFlag==false)
{
qDebug()<<"piece "+QString::number(threadNumber)+" download complete";
emit this->signalPieceFinished();
}
else
{
qDebug()<<"piece download abort(pause)";
emit this->signalPieceAbort();
}
}

void PieceThread::stopTheThread()
{
pauseFlag=true;
reply->abort();
qDebug()<<"piece download pause";
}



but the fault happend too.
:crying:

MarekR22
16th March 2011, 08:45
following is the detail code,
slotReadReady() will be called from subclass QThread
Nope, you are wrong. Take a look on QObject::connect, there is fifth argument with default value Qt::AutoConnection.
So connect will detect that qnam is created in PieceThread and PieceThread was created in main thread and will create queued connection, so this slot will be run in main thread.

Really move this new functionality to separate QObject instead subclassing QThread. You will gain more flexibility (you can do test without QThread), you will solve problems with this slotReadReady.

yaohao@qtcentre
17th March 2011, 09:01
I've tried what you say(move this new functionality to separate QObject instead subclassing QThread),and the program works wonderful now!



that qnam is created in PieceThread and PieceThread was created in main thread and will create queued connection


it means that the signal "readyRead" is emited in subthread,and the slot(slotReadyRead) is run in main,so it equals Qt::QueuedConnection,right?

thank for your help!
you are so professional!