Hello!
I'm writing a small program in Qt 5.0 under Windows 7 with msvc2010 toolchain. But in the process of writing I met a rather problem: Exception. Access violation - code c0000005.
Created a test project that enclose below.
The problem as follows:
I'm creating a "thread", in which a "test" is being perfomed. "Test" creates another "thread", which runs in an endless cycle of reading. In the test I create CCANReceiver, which begins to read data from the device, and then send the data. I wait for 5 seconds and close the thread with CCANReceiver. But when trying to call StopReceiving () function while calling IsRunning () I get the exception. Empirically I found that if a function ReadDMADataOneBlock
ReadDMADataOneBlock () - function of libraries provided by me to work with the device. The source codes are available.
Source code in attachment. I do not include the library, because without the device driver and it will not work, but I can put the source code.
Detailed error information:
(d08.d68): Access violation - code c0000005 (first chance)
s
sException at 0x6704c87c, code: 0xc0000005: write access violation at: 0x1, flags=0x0 (first chance) at q:\qt5_workdir\w\s\qtbase\src\corelib\arch\qatomic _msvc.h:351
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=00000001 edx=00000040 esi=00000007 edi=01d6dfc4
eip=6704c87c esp=01d6d444 ebp=01d6d444 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
Qt5Cored!QAtomicOps<QMutexData *>::testAndSetRelaxed+0xc:
3516704c87c f00fb10a lock cmpxchg dword ptr [edx],ecx ds:0023:00000040=????????
Call stack at the moment of program down:
0 QAtomicOps<QMutexData *>::testAndSetRelaxed qatomic_msvc.h 351 0x6704c87c
1 QGenericAtomicOps<QAtomicOps<QMutexData *> >::testAndSetAcquire<QMutexData *,QMutexData *> qgenericatomic.h 150 0x6704a8a5
2 QBasicAtomicPointer<QMutexData>::testAndSetAcquire qbasicatomic.h 229 0x67048e08
3 QBasicMutex::fastTryLock qmutex.h 87 0x670486f7
4 QMutex::lock qmutex.cpp 212 0x67069e11
5 QMutexLocker::QMutexLocker qmutex.h 133 0x670487e8
6 QThread::isRunning qthread.cpp 448 0x67070243
7 CCANReceiver::StopReceiving ccanreceiver.cpp 45 0x41c5e3
I do not understand how this could happen.
Debugging, I found out that this is most likely due to the fact that QScopedPointer >::data returns a value of 0.
Call stack:
0 QScopedPointer<QObjectData,QScopedPointerDeleter<Q ObjectData> >::data qscopedpointer.h 135 0x67041d4c
1 qGetPtrHelper<QScopedPointer<QObjectData,QScopedPo interDeleter<QObjectData> > > qglobal.h 991 0x670581ab
2 QThread::d_func qthread.h 136 0x670573d3
3 QThread::isRunning qthread.cpp 446 0x67070231
4 CCANReceiver::StopReceiving ccanreceiver.cpp 44 0x420423
5 CTest0::OnTimerTimeOut ctest0.cpp 324 0x41580e
Some source code:
ctest0.h
#ifndef CTEST0_H
#define CTEST0_H
#include "itest.h"
#include "CANDeviceEx.h"
#include "ccanreceiver.h"
#include <QTimer>
class CTest0 : public ITest
{
Q_OBJECT
public:
CTest0(ILogger* _Logger);
virtual void SetFeature(quint64 NumFeat, quint64 ValFeat);
public slots:
virtual void Run();
void OnTimerTimeOut();
public:
virtual ~CTest0();
private:
CCANDeviceEx CANDevice;
CCANReceiver *CANReceiver;
quint32 sendbuff[3];
quint32 mode1, mode2, sendchannel, bufnum;
quint8 brp1, sjw1, sam1, btlmode1, phseg11, phseg21, prseg1, wakfil1;
quint8 brp2, sjw2, sam2, btlmode2, phseg12, phseg22, prseg2, wakfil2;
};
#endif // CTEST0_H
#ifndef CTEST0_H
#define CTEST0_H
#include "itest.h"
#include "CANDeviceEx.h"
#include "ccanreceiver.h"
#include <QTimer>
class CTest0 : public ITest
{
Q_OBJECT
public:
CTest0(ILogger* _Logger);
virtual void SetFeature(quint64 NumFeat, quint64 ValFeat);
public slots:
virtual void Run();
void OnTimerTimeOut();
public:
virtual QString GetName() const;
virtual ~CTest0();
private:
CCANDeviceEx CANDevice;
CCANReceiver *CANReceiver;
quint32 sendbuff[3];
QTimer* Timer;
quint32 mode1, mode2, sendchannel, bufnum;
quint8 brp1, sjw1, sam1, btlmode1, phseg11, phseg21, prseg1, wakfil1;
quint8 brp2, sjw2, sam2, btlmode2, phseg12, phseg22, prseg2, wakfil2;
};
#endif // CTEST0_H
To copy to clipboard, switch view to plain text mode
ctest0.cpp
#include "ctest0.h"
CTest0::CTest0(ILogger* _Logger) :
ITest(_Logger),
CANReceiver(NULL),
Timer(NULL)
{
}
void CTest0::Run()
{
quint32 tmp = 0;
quint32 tmpmode = 0;
sendbuff[0] = 0x01020304;
sendbuff[1] = 0x05060708;
sendbuff[2] = 0x090A0B0C;
if (CANReceiver != NULL)
{
delete CANReceiver;
CANReceiver = NULL;
}
if (Timer != NULL)
{
delete Timer;
Timer = NULL;
}
if (CANDevice.IsOpen())
CANDevice.Close();
QObject::connect(Timer,
SIGNAL(timeout
()),
/*qobject_cast<CTest0*>*/(this),
SLOT(OnTimerTimeOut
()));
QObject::connect(Timer,
SIGNAL(qr
()),
this,
SLOT(OnTimerTimeOut
()));
Timer->setInterval(5000);
Timer->setSingleShot(true);
/* ... */
Logger->AddToLog("Trying to receive data");
CANReceiver = new CCANReceiver(&CANDevice);
CANReceiver->StartReceiving();
Logger->AddToLog("Start 5s wait");
Timer->start();
Logger
->AddToLog
("Trying to send data over " + QString::number(sendchannel
) + QString::number(bufnum
));
if ((tmp = CANDevice.SendData(sendchannel, bufnum, 0, sendbuff, 12)) != 1)
{
SetError
("Can't send data, error = " + QString::number(tmp
));
Timer->stop();
emit TestEnd();
return;
}
Logger
->AddToLog
("Send " + QString::number(sizeof(sendbuff
)) + " bytes");
}
void CTest0::SetFeature(quint64 NumFeat, quint64 ValFeat)
{
switch (NumFeat)
{
case 0:
mode1 = ValFeat;
break;
case 1:
mode2 = ValFeat;
break;
/* ... */
case 19:
bufnum = ValFeat;
break;
default:
break;
}
}
CTest0::~CTest0()
{
if (CANDevice.IsOpen())
CANDevice.Close();
if (CANReceiver != NULL)
delete CANReceiver;
if (Timer != NULL)
delete Timer;
}
{
return "Test 0";
}
void CTest0::OnTimerTimeOut()
{
Logger->AddToLog("Stop 5s wait");
CANReceiver->StopReceiving();
if (!CANReceiver->GetLastError().isEmpty())
{
SetError("Can't receive data, error \"" + CANReceiver->GetLastError() + "\"");
emit TestEnd();
return;
}
Logger
->AddToLog
("Succesfully receive " + QString::number(CANReceiver
->GetBufferSize
()) + " bytes");
}
#include "ctest0.h"
CTest0::CTest0(ILogger* _Logger) :
ITest(_Logger),
CANReceiver(NULL),
Timer(NULL)
{
}
void CTest0::Run()
{
quint32 tmp = 0;
quint32 tmpmode = 0;
sendbuff[0] = 0x01020304;
sendbuff[1] = 0x05060708;
sendbuff[2] = 0x090A0B0C;
if (CANReceiver != NULL)
{
delete CANReceiver;
CANReceiver = NULL;
}
if (Timer != NULL)
{
delete Timer;
Timer = NULL;
}
if (CANDevice.IsOpen())
CANDevice.Close();
Timer = new QTimer;
QObject::connect(Timer, SIGNAL(timeout()), /*qobject_cast<CTest0*>*/(this), SLOT(OnTimerTimeOut()));
QObject::connect(Timer, SIGNAL(qr()), this, SLOT(OnTimerTimeOut()));
Timer->setInterval(5000);
Timer->setSingleShot(true);
/* ... */
Logger->AddToLog("Trying to receive data");
CANReceiver = new CCANReceiver(&CANDevice);
CANReceiver->StartReceiving();
Logger->AddToLog("Start 5s wait");
Timer->start();
Logger->AddToLog("Trying to send data over " + QString::number(sendchannel) + QString::number(bufnum));
if ((tmp = CANDevice.SendData(sendchannel, bufnum, 0, sendbuff, 12)) != 1)
{
SetError("Can't send data, error = " + QString::number(tmp));
Timer->stop();
emit TestEnd();
return;
}
Logger->AddToLog("Send " + QString::number(sizeof(sendbuff)) + " bytes");
}
void CTest0::SetFeature(quint64 NumFeat, quint64 ValFeat)
{
switch (NumFeat)
{
case 0:
mode1 = ValFeat;
break;
case 1:
mode2 = ValFeat;
break;
/* ... */
case 19:
bufnum = ValFeat;
break;
default:
break;
}
}
CTest0::~CTest0()
{
if (CANDevice.IsOpen())
CANDevice.Close();
if (CANReceiver != NULL)
delete CANReceiver;
if (Timer != NULL)
delete Timer;
}
QString CTest0::GetName() const
{
return "Test 0";
}
void CTest0::OnTimerTimeOut()
{
Logger->AddToLog("Stop 5s wait");
CANReceiver->StopReceiving();
if (!CANReceiver->GetLastError().isEmpty())
{
SetError("Can't receive data, error \"" + CANReceiver->GetLastError() + "\"");
emit TestEnd();
return;
}
Logger->AddToLog("Succesfully receive " + QString::number(CANReceiver->GetBufferSize()) + " bytes");
}
To copy to clipboard, switch view to plain text mode
ccanreceiver.h
#ifndef CCANRECEIVER_H
#define CCANRECEIVER_H
#include <QList>
#include "clasterror.h"
#include "CANDeviceEx.h"
#include <QThread>
#include "CANHeader.h"
class CCANReceiver;
class CCANReceiverHelper
: public QObject,
public CLastError
{
Q_OBJECT
public:
CCANReceiverHelper(CCANReceiver* _CANReceiver, CCANDeviceEx* _CANDevice);
~CCANReceiverHelper();
void StopWork();
public slots:
void DoWork();
private:
CCANReceiver* CANReceiver;
CCANDeviceEx* CANDevice;
bool Stopped;
_MSG_INPUT rcvblock;
};
class CCANReceiver : public CLastError
{
public:
CCANReceiver(CCANDeviceEx* _CANDevice);
~CCANReceiver();
void ClearBuffer();
QList<quint8> GetBuffer() const;
quint64 GetBufferSize() const;
void StartReceiving();
void StopReceiving();
friend class CCANReceiverHelper;
private:
void AddToBuffer(quint8 data);
private:
QList<quint8> buffer;
CCANReceiverHelper CANReceiverHelper;
};
#ifndef CCANRECEIVER_H
#define CCANRECEIVER_H
#include <QList>
#include "clasterror.h"
#include "CANDeviceEx.h"
#include <QThread>
#include "CANHeader.h"
class CCANReceiver;
class CCANReceiverHelper : public QObject, public CLastError
{
Q_OBJECT
public:
CCANReceiverHelper(CCANReceiver* _CANReceiver, CCANDeviceEx* _CANDevice);
~CCANReceiverHelper();
void StopWork();
public slots:
void DoWork();
private:
CCANReceiver* CANReceiver;
CCANDeviceEx* CANDevice;
bool Stopped;
_MSG_INPUT rcvblock;
};
class CCANReceiver : public CLastError
{
public:
CCANReceiver(CCANDeviceEx* _CANDevice);
~CCANReceiver();
void ClearBuffer();
QList<quint8> GetBuffer() const;
quint64 GetBufferSize() const;
void StartReceiving();
void StopReceiving();
friend class CCANReceiverHelper;
private:
void AddToBuffer(quint8 data);
private:
QList<quint8> buffer;
CCANReceiverHelper CANReceiverHelper;
QThread CANReceiverHelperThread;
};
To copy to clipboard, switch view to plain text mode
ccanreceiver.cpp
#include "ccanreceiver.h"
CCANReceiver::CCANReceiver(CCANDeviceEx *_CANDevice) :
CANReceiverHelper(this, _CANDevice)
{
buffer.clear();
CANReceiverHelper.moveToThread(&CANReceiverHelperThread);
QObject::connect(&CANReceiverHelperThread,
SIGNAL(started
()),
&CANReceiverHelper,
SLOT(DoWork
()));
}
CCANReceiver::~CCANReceiver()
{
}
void CCANReceiver::ClearBuffer()
{
buffer.clear();
}
QList<quint8> CCANReceiver::GetBuffer() const
{
return buffer;
}
quint64 CCANReceiver::GetBufferSize() const
{
return buffer.size();
}
void CCANReceiver::AddToBuffer(quint8 data)
{
buffer.append(data);
}
void CCANReceiver::StartReceiving()
{
if (!CANReceiverHelperThread.isRunning())
CANReceiverHelperThread.start();
}
void CCANReceiver::StopReceiving()
{
if (CANReceiverHelperThread.isRunning())
{
CANReceiverHelper.StopWork();
CANReceiverHelperThread.quit();
CANReceiverHelperThread.wait();
}
}
CCANReceiverHelper::CCANReceiverHelper(CCANReceiver *_CANReceiver, CCANDeviceEx *_CANDevice) :
CANReceiver(_CANReceiver),
CANDevice(_CANDevice),
Stopped(false)
{
}
void CCANReceiverHelper::StopWork()
{
Stopped = true;
}
CCANReceiverHelper::~CCANReceiverHelper()
{
}
quint64 fact(quint64 n)
{
if (n <= 1)
return 1;
else
return fact(n - 1) * n;
}
void CCANReceiverHelper::DoWork()
{
while (1)
{
quint32 res = 0;
quint32 tmp = 0;
do
{
if (Stopped)
return;
if ((tmp = CANDevice->GetDMAReadyStatus(&res)) != 1)
{
CANReceiver
->SetError
("Can't get DMA ready status, error = " + QString::number(tmp
));
return;
}
}
while (!res);
if ((tmp = CANDevice->ReadDMADataOneBlock((void*)&rcvblock)) != 1)
{
CANReceiver
->SetError
("Can't read DMA one block, error = " + QString::number(tmp
));
return;
}
for (quint8 i = 0; i < rcvblock.RXB0DLC.DLC; i++)
{
CANReceiver->AddToBuffer(rcvblock.data.all[i]);
}
}
}
#endif // CCANRECEIVER_H
#include "ccanreceiver.h"
CCANReceiver::CCANReceiver(CCANDeviceEx *_CANDevice) :
CANReceiverHelper(this, _CANDevice)
{
buffer.clear();
CANReceiverHelper.moveToThread(&CANReceiverHelperThread);
QObject::connect(&CANReceiverHelperThread, SIGNAL(started()), &CANReceiverHelper, SLOT(DoWork()));
}
CCANReceiver::~CCANReceiver()
{
}
void CCANReceiver::ClearBuffer()
{
buffer.clear();
}
QList<quint8> CCANReceiver::GetBuffer() const
{
return buffer;
}
quint64 CCANReceiver::GetBufferSize() const
{
return buffer.size();
}
void CCANReceiver::AddToBuffer(quint8 data)
{
buffer.append(data);
}
void CCANReceiver::StartReceiving()
{
if (!CANReceiverHelperThread.isRunning())
CANReceiverHelperThread.start();
}
void CCANReceiver::StopReceiving()
{
if (CANReceiverHelperThread.isRunning())
{
CANReceiverHelper.StopWork();
CANReceiverHelperThread.quit();
CANReceiverHelperThread.wait();
}
}
CCANReceiverHelper::CCANReceiverHelper(CCANReceiver *_CANReceiver, CCANDeviceEx *_CANDevice) :
CANReceiver(_CANReceiver),
CANDevice(_CANDevice),
Stopped(false)
{
}
void CCANReceiverHelper::StopWork()
{
Stopped = true;
}
CCANReceiverHelper::~CCANReceiverHelper()
{
}
quint64 fact(quint64 n)
{
if (n <= 1)
return 1;
else
return fact(n - 1) * n;
}
void CCANReceiverHelper::DoWork()
{
while (1)
{
quint32 res = 0;
quint32 tmp = 0;
do
{
if (Stopped)
return;
if ((tmp = CANDevice->GetDMAReadyStatus(&res)) != 1)
{
CANReceiver->SetError("Can't get DMA ready status, error = " + QString::number(tmp));
return;
}
}
while (!res);
if ((tmp = CANDevice->ReadDMADataOneBlock((void*)&rcvblock)) != 1)
{
CANReceiver->SetError("Can't read DMA one block, error = " + QString::number(tmp));
return;
}
for (quint8 i = 0; i < rcvblock.RXB0DLC.DLC; i++)
{
CANReceiver->AddToBuffer(rcvblock.data.all[i]);
}
}
}
#endif // CCANRECEIVER_H
To copy to clipboard, switch view to plain text mode
I beg for your help.
Sincerely, akaWolf.
Added after 8 minutes:
I described this problem before, but no one could help me.
Bookmarks