QThread eating up memory
-
Hi everyone,
I have created a program which will let a user draw someone onto an image and then be sent to another window to display, something like a whiteboard chat. So I have created 2 threads, one for transmitter and the other for receiver.
When I first started the program, the memory usage is about 8mb, but as I draw, the memory increases, up until about 13.1mb before it crashes. I got the data from task manager.
Please do help as I have no idea what is happening.
The follow are part of my code:
Transmitter:
mutex->lock(); // Transmitter ready sReady->wakeAll(); // wait for receiver to received ready and ack back to transmitter rAck->wait(mutex); // Transmitter receive ack and ack back to receiver sAck->wakeAll(); // Wait for receiver to be ready to receive data receive->wait(mutex); QByteArray c = charQ.dequeue(); QByteArray data = dataQ.dequeue(); QBitArray localDataBits; QBitArray localCharBits; localCharBits = byteToBits(c); localDataBits = byteToBits(data); for (int j = 0; j<c.count()*8; j++) { int write = localCharBits.at(j) ? 1 : 0; charBits[j] = write; } for (int j = 0; j<data.count()*8; j++) { int write = localDataBits.at(j) ? 1 : 0; dataBits[j] = write; } // Transmitter finish sending sent->wakeAll(); // Wait for receiver to receive data receive->wait(mutex); mutex->unlock();Receiver:
mutex->lock(); // Wait for transmitter to send ready sReady->wait(mutex); // Send ack to transmitter rAck->wakeAll(); // Wait for transmitter to send ack sAck->wait(mutex); // Receiver ready to receive receive->wakeAll(); // Wait for transmitter to finish sending data sent->wait(mutex); QBitArray readChar; readChar.resize(sizeof (QChar)*8); // to ensure it can hold all bits for (int n=0; n<readChar.size(); n++) { bool bit = (incomeChar[n]==1) ? true : false; readChar.setBit(n, bit); } // deserialise QByteArray rChar = bittobyte(readChar); QChar c; c = deserial<QChar>(rChar); QBitArray readdata; // to resize readata to ensure it can read all necessary bits if (c == 'p') { // coords readdata.resize(64); } else if (c == 't') { // toggle drawing and last coords readdata.resize(64); } else if (c == 'w') { // pen width readdata.resize(32); } else if (c == 'c') { // pen colour readdata.resize(88); } else if (c == 'e') { // eraser readdata.resize(88); } else if (c == 'P') { // pen readdata.resize(88); } else if (c == 'r') { // resize canvas readdata.resize(64); } else if (c == 'q') { // canvas colour readdata.resize(88); } else if (c == 'C') { // clear canvas readdata.resize(32); } for (int n=0; n<readdata.size(); n++) { bool bit = (incomeData[n]==1) ? true : false; readdata.setBit(n, bit); } QByteArray rdata = bittobyte(readdata); if (c == 'p') { // coords emit sendPosition(rdata); } else if (c == 't') { // toggle drawing and last coords emit sendToggle(rdata); } else if (c == 'w') { // pen width emit sendPenWidth(rdata); } else if (c == 'c') { // pen colour emit sendPenColour(rdata); } else if (c == 'e') { // eraser emit sendEraser(rdata); } else if (c == 'P') { // eraser emit sendPen(rdata); } else if (c == 'r') { // reisze canvas emit sendCanvasSize(rdata); } else if (c == 'q') { // reisze canvas emit sendCanvasColour(rdata); } else if (c == 'C') { // clear canvas emit sendClear(rdata); } // Receiver finish reading receive->wakeAll(); mutex->unlock(); if (!*complete) { // if window not close, prepare to receive emit done(); // call same function again, prepare for another receive when transmitter is ready }main.cpp:
QWaitCondition *sendState = new QWaitCondition; // transmitter state QWaitCondition *receiveState = new QWaitCondition; // receiver state // 'transmission medium' bool charStream[8]; bool dataStream[88]; // 3 way handshake QWaitCondition *senderReady = new QWaitCondition; QWaitCondition *receiverAck = new QWaitCondition; QWaitCondition *senderAck = new QWaitCondition; bool finish = 0; int main(int argc, char *argv[]) { QApplication a(argc, argv); drawing userWin; drawing receiveWin; userWin.resize(650, 650); receiveWin.resize(650, 650); userWin.type(false); // transmitter window receiveWin.type(true); // receiver window userWin.setWindowTitle("Draw"); receiveWin.setWindowTitle("Receive"); QThread transmitThread; QThread receiveThread; QMutex mutex; transmit *transmitter = new transmit(); receiver *receive = new receiver(); // move each object to their threads transmitter->moveToThread(&transmitThread); receive->moveToThread(&receiveThread); // Initialise by passing address of each stuff to transmitter and receiver transmitter->init(dataStream, charStream, sendState, receiveState, senderReady, receiverAck, senderAck , &mutex, &finish); receive->init(dataStream, charStream, sendState, receiveState, senderReady, receiverAck, senderAck, &mutex, &finish); // Transmit window to transmitter QObject::connect(&userWin, &drawing::sendData, transmitter, &transmit::queue); // to enable receiver to receive QObject::connect(&receiveThread, &QThread::started, receive, &receiver::receiveData); // Keep receiver running and waiting for data QObject::connect(receive, &receiver::done, receive, &receiver::receiveData); QObject::connect(&userWin, &drawing::windowClose, transmitter, &transmit::done); QObject::connect(&receiveWin, &drawing::windowClose, transmitter, &transmit::done); // connect from receiver to receive window QObject::connect(receive, &receiver::sendToggle, &receiveWin, &drawing::toggleDraw); QObject::connect(receive, &receiver::sendPosition, &receiveWin, &drawing::onReceivePos); QObject::connect(receive, &receiver::sendPenWidth, &receiveWin, &drawing::onPenSize); QObject::connect(receive, &receiver::sendClear, &receiveWin, &drawing::onClear); QObject::connect(receive, &receiver::sendPenColour, &receiveWin, &drawing::onPenColour); QObject::connect(receive, &receiver::sendEraser, &receiveWin, &drawing::onEraser); QObject::connect(receive, &receiver::sendPen, &receiveWin, &drawing::onPen); QObject::connect(receive, &receiver::sendCanvasSize, &receiveWin, &drawing::onResizeCanvas); QObject::connect(receive, &receiver::sendCanvasColour, &receiveWin, &drawing::onCanvasColour); transmitThread.start(); receiveThread.start(); userWin.move(250,150); receiveWin.move(1050,150); userWin.show(); receiveWin.show(); a.exec(); // end Thread and mutex transmitThread.quit(); transmitThread.terminate(); receiveThread.quit(); receiveThread.terminate(); mutex.~QMutex(); return 0; }Thank you.
Edit: I have edited the code to my latest version, replacing while loop with QWaitCondition
-
- Maunally calling destructors is a bad idea in 99.99999999999999999999999% of the cases
- You never actually start the threads so I'm not sure what you are expecting.
- You are doing a lot of low level stuff that is not necessary/useful
something like a whiteboard chat
Probably this example is a good starting point
-
I have done some more testing, when I exclude the thread, it works without the memory increasing overtime. But when I added thread, it starts to increase memory whenever the user does something.
I am passing the values by pointers, does that affect memory?
-
Hi,
Rather than looping like that waiting for something to arrive, why not make use of QWaitCondition ?
-
HI,
I did some searching and correct me if I am wrong, QWaitCondition when wait is called, it will lock the mutex, and wait for a condition then unlock it. But both my transmitter and receiver are using the same mutex, will that cause any issue? So far I have no luck trying to use it. -
I have successfully remove while loop and replace it with QWaitCondition. The lagging between sending and receiving window has gone.
But the memory is still increasing everytime the user draws (using Task Manager). Is this a normal thing? Or there is some memory leak.
The receiver will keep on running and be ready to receive whereas the transmitter will wait until user make changes to the canvas.
-
It depends on how you manage your drawing. If it's a new object each time then yes, that's normal as you are using new objects.
-
It depends on how you manage your drawing. If it's a new object each time then yes, that's normal as you are using new objects.
@SGaist Sorry for being dumb here, but when you say create new object, do you mean creating variables?
Like inside my function there's QByteArray A, but it was not destroyed when the program is running so it create more of itself?
Could you also please give an example, as I am abit clueless.