Qt Application Memory Usage - c++

I'm working on an application that involves using real time, continuous, audio input, for which I'm using portaudio. I created simple cli version first in order to set things up and the memory usage in the cli version seemed fine. In the CLI version, while the recording was on, no extra memory was being allocated aside from the initial buffer.
However, in the process of applying the same code from the CLI to a GUI (for which, I'm using Qt), I notice that as the recording proceeds, the memory being used by the application constantly increases (by about 3 mb/sec). Since my application involves audio input for an undefined amount of time, such behaviour can be extremely fatal and thus,I started stripping off segments from the code inorder to check which area was responsible for this memory being used. (note that this behavior was NOT being observed from the cli version, and that nearly the same code was used in qt, aside from the addition of a Q_OBJECT macro)
I tried this for a while but could not find anything.
I am relatively new to using Qt and would greatly appreciate some help with this
My widget apps header file
#ifndef DETECTORMAIN_H
#define DETECTORMAIN_H
#include <QMainWindow>
#include <QThread>
#include <QPointer>
#include "utils/rectools.h" /*Custom header file, the implementation of
which has been carried over from the cli version
which worked with constant memory usage.
Contains a class Recorder with the Q_OBJECT macro*/
QT_BEGIN_NAMESPACE
namespace Ui { class detectorMain; }
QT_END_NAMESPACE
class detectorMain : public QMainWindow
{
Q_OBJECT
public:
detectorMain(QWidget *parent = nullptr);
~detectorMain();
private slots:
void on_beginRecordingButton_clicked();
void on_stopRecordingButton_clicked();
void updateVolLabel(std::string);
private:
Ui::detectorMain *ui;
QPointer<Recorder> recorder;
QThread* thread;
};
#endif // DETECTORMAIN_H
Source file
#include "detectormain.h"
#include "ui_detectormain.h"
detectorMain::detectorMain(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::detectorMain)
{
ui->setupUi(this);
recorder = new Recorder;
thread = new QThread;
recorder->moveToThread(thread);
thread->start();
ui->beginRecordingButton->setEnabled(true);
ui->stopRecordingButton->setEnabled(false);
connect(recorder, SIGNAL(UpdateVols(std::string)), this, SLOT(updateVolLabel(std::string)));
}
detectorMain::~detectorMain()
{
delete ui;
}
void detectorMain::on_beginRecordingButton_clicked()
{
ui->beginRecordingButton->setEnabled(false);
ui->stopRecordingButton->setEnabled(true);
recorder->begin_recording();
}
void detectorMain::on_stopRecordingButton_clicked()
{
recorder->stop_recording();
ui->beginRecordingButton->setEnabled(true);
ui->stopRecordingButton->setEnabled(false);
}
void detectorMain::updateVolLabel(std::string vol)
{
ui->VolLabel->setText(QString::fromStdString(vol));
QCoreApplication::processEvents();
}
The function Recorder::begin_recording() emits UpdateVols(std::string) where UpdateVols is a signal in the Recorder class. It emits at a pretty fast rate (around 1 every ms). Does this have something to with the memory usage increasing?
In the CLI version I could just cout whatever I needed to and this is the most major difference in code between the CLI version and the Qt version.
The memory usage does not reduce after the begin_recording() function has finished execution though which confuses me.
For example, the app starts at 9 mb memory usage, increases to about 39 when begin_recording() runs for 10 seconds, and stays at 39mb when not doing anything afterwards.
If it was the fast emit rate, I assume that the memory usage will return to normal when it is no longer emitting.
Additionally, in the above code, when the beginRecordingButton is clicked, the app becomes unresponsive, but resumes once the function recorder->begin_recording() has finished execution. I guess this has something to do with the memory increasing constantly but I'm not too sure.
I believe the error to lie somewhere in how I'm using the QThread object and moving the recorder object to it, but I'm not sure how to fix it.
In the process of finding out where the memory usage was being increased, I tried running a bare app with just the buttons and labels, not involving the recorder class at all. On simply opening this app with zero functionality, the memory usage kept increasing by about 0.5mb whenever it showed a non zero CPU utilization. After increasing, it does not fall down even if the cpu utilisation was 0.
Overall, I would like to ask,
1)How can I fix the issue of the memory usage constantly increasing? (I don't think the error lies in the Recorder class as the same code runs without qt at constant memory)
2)Is the behavior mentioned in the final paragraph normal?

What #G.M. said in the comments worked. Thank You
The problem was the emit rate. 1khz is too fast and a lot gets build up.

Related

QDialog box showing blank when MainWindow thread is busy

I am working on a Qt-C++ based front-end app for a Raspberry Pi powered robot. I am using Qt version 5.9 along with libraries QSerialPort and Pigpio. In my app, when I give the run command for a command sequence to the robot, my Raspberry Pi starts a serial communication with a microcontroller in which it sends some message and then waits to receive a response. This sending and waiting causes the Mainwindow thread to freeze up. I am trying to build in a emergency stop functionality, which would stop the command execution in the middle of the run process.
Towards that effort, I tried to push my serial communication part to a separate thread(QThread). It didn't work out. Now I am trying to build the emergency stop part into a QDialog box that opens up when I give the run command, which contains a emergency stop QPushbutton. The Dialog box is being run in non-modal form. But in my current code, when I give the run command, a dialog box does open up, but the dialog box is completely blank and then closes up when the run command ends(which is intentional). I'll share some screenshots of the appearance.
Can you suggest where I might be going wrong? Or is there a better approach to this issue? Any criticism and suggestions are welcome!
Thanks!
One shouldn't block the main thread in the Qt. Everytime you call the blocking function, your GUI freezes, as well as Dialog boxes.
One solution is to use signal/slots. They blend really well into Qt. But doing a complicated request/response logic would require a huge state machine usually prone to errors.
Sometimes it is better to leave this code blocking, create a plain chain of request/response code, and put it in another non-GUI thread. Then use the signal to notify the main thread about the job result.
In order to stop the execution it is possible to use an atomic and check it between blocking steps. The biggest time delay before exiting the working function is the biggest delay of the single blocking function. You should carefully tune the timeouts. Or you can write your own function, which emulates timeout and a stop condition. It should check if incoming data is available in an infinite loop and check fro stop condition on each iteration, which must be a timeout AND a stop condition variable.
// pseudocode here
while (true) {
if (stopCondition) return; // check for emergency condition
it (currentTime - startTime > timeout) return;
if (serial->dataReady()) break;
}
auto data = serial->getData();
If a step can block forever, then this method can't be used.
There is an example with QtConcurrent framework, which demonstrates the use of QFuture and the work of a function in a separate thread without blocking the main thread. You can put all your communication logic inside it.
The code is example only!
#ifndef WORKERCLASS_H
#define WORKERCLASS_H
#include <QObject>
#include <QtConcurrent/QtConcurrent>
#include <QFuture>
class WorkerClass : public QObject
{
Q_OBJECT
public:
explicit WorkerClass(QObject *parent = nullptr) : QObject(parent) {
connect(&futureWatcher, &QFutureWatcher<void>::finished, [this] () {
emit workFinsihed();
});
}
void startWork(int value) {
atomic = 0;
future = QtConcurrent::run(this, &WorkerClass::workFunction, value);
futureWatcher.setFuture(future);
}
void stopWork() {
atomic = 1;
}
private:
QFuture<void> future;
QFutureWatcher<void> futureWatcher;
void workFunction(int value) {
for (int i = 0; i < value; ++i) {
if (atomic) return;
}
return;
};
QAtomicInt atomic{0};
signals:
void workFinsihed();
};
#endif // WORKERCLASS_H

multithreaded Qt+OpenCV

I am going to make a thread which recieves the image from webcam camera, using opencv and Mat type. then I convert it to QImage and send it to main thread using a signal. when I want to visualize it in a QLabel object in ui (after converting to a pixmap) I get this error:
The program has unexpectedly finished.
here is my camera class:
camera.h:
#ifndef CAMERA_H
#define CAMERA_H
#include <QObject>
#include <QThread>
#include <QtCore>
#include <QtGui>
#include <opencv2/opencv.hpp>
using namespace cv;
class Camera: public QThread
{
Q_OBJECT
public:
Camera();
void run();
bool Stop = false;
signals:
void ImgSignal(QImage*);
private:
public slots:
};
#endif // THREAD_H
camera.cpp:
#include "camera.h"
#include <iostream>
using namespace std;
Camera::Camera()
{
}
void Camera::run()
{
VideoCapture cap;
cap.open(0);
while(1){
Mat img;
cap >> img;
cvtColor(img,img,CV_BGR2RGB);
QImage image = QImage((const uchar*)img.data,img.cols,img.rows,img.step,QImage::Format_RGB888);
emit ImgSignal(&image);
QThread::msleep(30);
}
}
and finally my onImgSignal function that recieves the image and passes it to gui:
void MainWindow::onImgSignal(QImage *img)
{
QPixmap *p;
p->fromImage(*img);
ui->label->setPixmap(*p);
}
I would be so glad if you help me. thanks!
Edit
when I changed the pixmap poiner to a pixmap variable the error did not come up but the pixmap variable is null. even if i load an image separately it will be null:
QPixmap p;
p.load("mark.png");
cout << p.isNull();
ui->label->setPixmap(p);
My first hunch is that some pointer to some object/memory are accidentally accessed by two different threads at the same time, creating an access violation. So by just making a COPY of the image you pass around might do the trick (so both threads arn't accessing the pixel data of the same image at the same time). Here are some other things you can do to address that:
First, the threads implementation in Qt is a bit unconventional. For example, it is not considered best practice to extend the QThread class like you have done, as the QThread instance will NOT live in the new OS level thread. Yes! It's true. This leads to many sources of confusion that in turn lead to bugs. To read the official unofficial guide on how to do threads correctly in Qt, please look at this excellent article. Short summary: QThread class will act as a "management" class living in the execution thread where you instantiated it, so first tip is to learn this, and use the QThread class as intended.
Second, Qt is supposed to guess during signal time when the source and destination are in same thread or not, however I have found that it sometimes, just for the peace of mind, pays to be specific about how signals will be passed. That is why my code is full of this:
if(!connect(this,SIGNAL(colorChanged(QColor)),&ob,SLOT(onColorChanged(QColor)),(Qt::ConnectionType) (Qt::QueuedConnection | Qt::UniqueConnection) )) {
qWarning()<<"ERROR: Could not connect "<<ob.objectName();
}
Notice the last parameter to the connect call, as it specifies Qt::QueuedConnection and Qt::UniqueConnection connections. Qt::QueuedConnection means that it is "thread safe" in that it will store the signal in a thread safe FIFO. Qt::UniqueConnection just means that connecting twice will generate an error the second time instead of creating two connections (which may lead to hard-to-trace bugs).
Third, are you starting any threads without using Qt? In that case care should be taken with signals, because they might not work properly unless you are working with Qt initiated threads. I THINK the Qt::QueuedConnection trick above should be enough, but I don't know. Here is more. Oh, and if OpenCV ever decides to knowingly or unknowingly start some threads of it's own, they will count as "threads started outside Qt".
Fourth, did you run this in a debugger? At what exact point did it crash? This should be your first move, btw.
Fifth, If all else fails wrap your code in a QMutex and use QMutexLocker to ensure that there is no problems. Or you could get fancy and use some thread safe containers or some such.
PS: Please let me know how you fare!

Qt - updating main window with second thread

i have an multithreaded qt application. when i am doing some processes in mainwindow.cpp, at the same time, i want to update mainwindow.ui from other thread.
i have mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include "mainwindow.h"
class mythread : public QThread
{
public:
void run();
mythread( MainWindow* ana );
MainWindow* ana;
private:
};
#endif // MYTHREAD_H
mythread.cpp
mythread::mythread(MainWindow* a)
{
cout << "thread created" << endl;
ana = a;
}
void mythread::run()
{
QPixmap i1 (":/notes/pic/4mdodiyez.jpg");
QLabel *label = new QLabel();
label->setPixmap(i1);
ana->ui->horizontalLayout_4->addWidget(label);
}
but the problem is that, i cannot reach the ana->ui->horizontalLayout_4->addWidget(label);
how can i do that?
but the problem is that, i cannot reach the
ana->ui->horizontalLayout_4->addWidget(label);
Put your UI modifications in a slot in your main window, and connect a thread signal to that slot, chances are it will work. I think only the main thread has access to the UI in Qt. Thus if you want GUI functionality, it must be there, and can be only signaled from other threads.
OK, here is a simple example. BTW, your scenario doesn't really require to extend QThread - so you are better off not doing it, unless you really have to. That is why in this example I will use a normal QThread with a QObject based worker instead, but the concept is the same if you subclass QThread:
The main UI:
class MainUI : public QWidget
{
Q_OBJECT
public:
explicit MainUI(QWidget *parent = 0): QWidget(parent) {
layout = new QHBoxLayout(this);
setLayout(layout);
QThread *thread = new QThread(this);
GUIUpdater *updater = new GUIUpdater();
updater->moveToThread(thread);
connect(updater, SIGNAL(requestNewLabel(QString)), this, SLOT(createLabel(QString)));
connect(thread, SIGNAL(destroyed()), updater, SLOT(deleteLater()));
updater->newLabel("h:/test.png");
}
public slots:
void createLabel(const QString &imgSource) {
QPixmap i1(imgSource);
QLabel *label = new QLabel(this);
label->setPixmap(i1);
layout->addWidget(label);
}
private:
QHBoxLayout *layout;
};
... and the worker object:
class GUIUpdater : public QObject {
Q_OBJECT
public:
explicit GUIUpdater(QObject *parent = 0) : QObject(parent) {}
void newLabel(const QString &image) { emit requestNewLabel(image); }
signals:
void requestNewLabel(const QString &);
};
The worker object is created and moved to another thread, then connected to the slot that creates the labels, then its newLabel method is invoked, which is just a wrapper to emit the requestNewLabel signal and pass the path to the image. The signal is then passed from the worker object/thread to the main UI slot along with the image path parameter and a new label is added to the layout.
Since the worker object is created without parent in order to be able to move it to another thread, we also connect the thread destroyed signal to the worker deleteLater() slot.
First and foremost, "you're doing it wrong". Normally you want to create a class derived from a QObject and move that class to a new thread object instead of deriving your class from a Qthread
Now to get onto the specifics of your question, you're not able to directly modify the ui elements of your main GUI thread from a separate thread. You have to connect a signal from your 2nd thread to a slot in your main thread. You can pass any data that you need through this signal/slot connection but you're unable to directly modify the ui element (which in all honestly you probably do not want to if you intend to keep the frontend of your app separate from the backend). Checkout Qt's signal and slot documentation for a whole lot more information
how can i do that?
You've already got the answers to what you should be doing, but not a why, so I'm going to add a why.
The reason you don't modify GUI elements from another thread is because GUI elements are usually not thread-safe. This means that if both your main GUI thread and your worker thread update the UI, you cannot be certain of the order of what happened when.
For reading data generally this can sometimes be fine (e.g. checking a condition) but generally you do not want this to be case. For writing data, this is almost always the source of very, very stressful bugs which occur "at random".
Another answer has remarked on good design principles - not only does constraining your GUI logic to one thread and firing signals to talk to it get rid of your race condition issues, but it also forces you to compartmentalize your code nicely. Presentation logic (the display bit) and data processing logic can then be cleanly separated out, which makes maintaining the two much easier.
At this stage you might think: heck, this threads business is farrrrrr too much work! I'll just avoid that. To see why this is a bad idea, implement a file copy program in a single thread with a simple progress bar telling you how far along the copy is. Run it on a large file. On Windows, after a while, the application will "go white" (or on XP I think it goes gray) and will be "not responding". This is very literally what is happening.
GUI applications internally mostly work on the variation of "one big loop" processing and dispatching messages. Windows, for example, measures response time to those messages. If a message takes too long to get a response, Windows then decides it is dead, and takes over. This is documented in GetMessage().
So whilst it may seem like quite a bit of work, Signals/Slots (an event-driven model) is basically the way to go - another way to think of this is that it is totally acceptable for your threads to generate "events" for the UI too - such as progress updates and the like.

Headless QT4 OpenGL Application

I'm working on creating a headless console application in QT4 that does some OpenGL rendering and then ships the result out across the network via a websocket. I have all of the rendering and network code running (assuming that I have a GUI), but I am having some trouble transitioning to a headless application. Is it possible to create a QGLContext without having a window?
Reading on the web hasn't turned up much, but from what I have gathered you can create a QGLPixelBuffer which is a valid QPaintDevice. It seems to create its own private QGLContext that it uses for hardware accelerated drawing. The problem that I am having with this route is that I need access to it's underlying QGLContext so that I can share it with another thread (network thread for fast DMA texture transfers out of the rendered scene). Included below is a small prototype. Any ideas?
Application.h
/**
#file
#author Nikolaus Karpinsky
*/
#ifndef _APPLICATION_H_
#define _APPLICATION_H_
#include <QCoreApplication>
#include <QTimer>
#include "MainController.h"
#endif // _APPLICATION_H_
Application.cpp
#include "Application.h"
int main(int argc, char **argv)
{
// Setup our console application with an event loop
QCoreApplication app(argc, argv);
// Create and initialize our controller
MainController controller;
controller.Init();
QObject::connect(&controller, SIGNAL( Finished() ), &app, SLOT( quit() ), Qt::QueuedConnection);
// This will put start on top of the event loop
QTimer::singleShot(0, &controller, SLOT( Start() ));
// Finally start up the event loop
return app.exec();
}
MainController.h
/**
#file
#author Nikolaus Karpinsky
*/
#ifndef _MAIN_CONTROLLER_H_
#define _MAIN_CONTROLLER_H_
#include <QObject>
#include <QGLWidget>
#include <QGLPixelBuffer>
#include <QGLFramebufferObject>
#include <memory>
using namespace std;
class MainController : public QObject
{
Q_OBJECT
private:
unqiue_ptr<QGLPixelBuffer> m_mainBuffer;
//unique_ptr<QGLContext> m_mainContext;
public:
MainController();
void Init(void);
public slots:
void Start(void);
void Close(void);
signals:
void Finished(void);
};
#endif // _MAIN_CONTROLLER_H_
MainController.cpp
#include "MainController.h"
MainController::MainController() : QObject()
{ }
void MainController::Init(void)
{
m_mainBuffer = unique_ptr<QGLPixelBuffer>(new QGLPixelBuffer(800, 600));
bool has = buffer->hasOpenGLPbuffers();
bool current = buffer->makeCurrent();
bool valid = buffer->isValid();
// Now I need to get access to the context to share it with additional threads
// m_mainContext = unique_ptr<QGLContext>(new QGLContext(buffer.getContext()));
}
void MainController::Start(void)
{
}
void MainController::Close(void)
{
// This will tell the event loop that we are done and close the app
emit( Finished() );
}
Is it possible to create a QGLContext without having a window?
Yes, but there is a catch…
Reading on the web hasn't turned up much, but from what I have gathered you can create a QGLPixelBuffer which is a valid QPaintDevice.
Yes, but that PBuffer still needs to talk to the GPU. And in Linux the usual way to talk to the GPU is through the X server. So you actually need an X server, using the GPUs drivers, to be launched and the active VT so that a PBuffer can work on the GPU.
Hopefully there will be a new ABI/API to GPUs soon, that allows you to create offscreen render contexts on a GPU without having an X server around.
The problem that I am having with this route is that I need access to it's underlying QGLContext so that I can share it with another thread (network thread for fast DMA texture transfers out of the rendered scene).
Unfortunately the Qt developers have only limited knowledge about OpenGL, as it seems. Several things that are perfectly possible with OpenGL and well specified are not possible with Qt for no apparent reason. For example you can have an arbitrary number of contexts using a single drawable. But you can also use single context on an arbitrary number of (compatible) drawables by rebinding it. Neither is supported by Qt and a clear design flaw. I'm struggling with this myself right now.
Ok, so after some playing around I found a good enough solution. Currently I am running my application as a QApplication vs QCoreApplication. From here I create a QGLWidget on the GUI thread and then immediately call updateGL() on the widget which creates and initalizes the OpenGL context. Assuming I don't ever make the app visible it runs "headless" but still gets the QT needed window handle from X or Explorer.
Going a bit deeper, I also needed to get shared QGLContexts on other threads. To make copies of the context from the QGLWidget I simply create a QGLWidget using the deprecated constructor where you can specify a painter (QGLWidget) and then create using the QGLWidgets context. I posted an example below to show. Using this I can write textures in one thread and process in another while keeping the app "headless". Thanks for the help datenwolf.
shared_ptr<QGLContext> MainController::MakeSharedContext(void)
{
shared_ptr<QGLContext> sharedContext(nullptr);
if(nullptr != m_mainContext)
{
// m_mainContext is: shared_ptr<QGLWidget>
sharedContext = shared_ptr<QGLContext>( new QGLContext(m_mainContext->format(), m_mainContext.get( ) ) );
bool created = sharedContext->create( m_mainContext->context( ) );
Utils::AssertOrThrowIfFalse(created, "Unable to create a shared OpenGL context" );
}
return sharedContext;
}

QPlainTextEdit throwing std::bad_alloc

I have a program that runs a least squares fit to some data. This procedure is run in a separate thread and controlled from a dialog box. This dialog box has a QPlainTextEdit that shows fitting updates and a final report.
The dialog was created in Qt Designer, the code is run into QtCreator and my Qt version is 4.8.1.
The problem I am running into is somewhat erratic. When I run the procedure a first time, everything is fine. Then if I run it again, sometimes the program crashes with the message
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
The program has unexpectedly finished.
I tracked the problem to a call to the clear() method of a QPlainTextEdit. Here is some code.
// Snippets of the class definition
class QLSQDialog : public QDialog, public Ui_QLSQDialog
{
Q_OBJECT
public:
QLSQDialog(QWidget *parent = 0);
(...)
void UpdateDisplay(const QString &msg, int iter, double norm); // Update values of chi, etc on displays
signals:
void Run(); // Signal to run a LSQ procedure
(...)
private slots:
void on_btnRun_clicked();
(...)
private:
void Enables(bool running); // Enable and disable features depending on running state of LSQ fit
(...)
};
// Snippets of the class implementation
QLSQDialog::QLSQDialog(QWidget *parent) : QDialog(parent)
{
setupUi(this); // Set up dialog
(...)
txtInfo->clear(); // txtInfo is a QPlainTextEdit created in Designer
(...)
}
void QLSQDialog::UpdateDisplay(const QString &msg, int iter, double norm)
{
lblChi->setText(QString::number(norm,'f',12));
if (iter >= 0) lblIt->setText(QString::number(iter));
txtInfo->appendPlainText(msg);
}
void QLSQDialog::on_btnRun_clicked()
{
txtInfo->clear(); // Offending line in second run
Enables(true);
emit Run();
}
void QLSQDialog::Enables(bool running)
{
bool Idle = !running;
bool HasReport = !txtInfo->document()->isEmpty();
(...)
btnReport->setEnabled(Idle && HasReport);
}
txtInfo is the QPlainTextEdit object. I call a txtInfo->clear() when the object is
created to show an empty text edit. When I click on a 'Run' tool button its default slot emits a Run signal that will start the new thread. The txtInfo QPlainTextEdit is updated in this thread until it finishes (in fact the thread emits a signal that is caught in the main application that in turn calls the UpdateDisplay).
If I click on the run button a second time, then I get the crash and the error. If I replace txtInfo->clear(), txtInfo->document()->clear(), by txtInfo->setPlainText("") or by txtInfo->document()->setPlainText("") the problem is the same (crash at second execution). Occasionally, but not frequently, I can run a few times (of the order of 10) before crashing.
Finally, if I comment out the txtInfo->clear() line, then I can run the routine as much as I tried (in one test I got tired after running it about 80 times).
My only (almost random) guess is that the problem is somehow related to the update from the thread (which emits a signal that is caught and in turn just calls the UpdateDisplay function). The reason I think so is that if I comment out the signals and just create a new button to call the UpdateDisplay with some bogus information, everything is fine.
A qApp->processEvents() before the offending line has no effect.
I am stuck here. Any ideas are welcome. For instance, is there any test I can do to verify that calling the clear() method is ok?
I finally tracked this problem down to a nasty memory leak in my code. I "repaired" the code but I am still a little bit puzzled by why the problem was happening.
Basically, I was creating a large vector<double> somewhere and passing its address to a function that called for a vector<double> * variable. The problem was that the original vector ceased to be before the function finished working with. Classic dumb mistake. Probably the QPlainTextEdit document was allocating space in the area where the vector<double> used to be: erratic behavior expected. But I would not expect a crash.
The vector was "read-only". The function using it, only read the values and made calculations stored somewhere else. Let's now assume that the plain text creates something in the memory previously addressed by the vector<double>. In this case, when I QPlainTextEdit::clear() the plain text document, the values previously pointed by the vector change and I would expect the calculations to be non sense. I would also accept a crash when the function access the now deceased pointer to vector<double>. But I would not expect the program to crash when I clear the text, which after all is a valid pointer.
Anyway, if anybody has a though, I'd be curious to know why the crash happens. But otherwise, the problem is gone once the leak was repaired. And of course, knowing the reason is absolutely no excuse to not repair the leak.