C++ 4.8 Runtime Heap corruption - c++

We are working with Qt 4.8, but I honestly believe this has nothing to do with it (but I point it out just in case)
We created this class that compiles just fine but crashes on runtime with the following error:
*ERROR:
53:01
Windows has triggered a breakpoint in C_plus_plus_QT_project.exe.
This may be due to a corruption of the heap, which indicates a bug in C_plus_plus_QT_project.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while C_plus_plus_QT_project.exe has focus.
The output window may have more diagnostic information.*
The problem is that QFrame m_FrameHeader; is declared on the .h file and the on the class constructor we go and do:
QFrame m_FrameHeader(this);
I am honestly surprised this compiles. If this would've been a test and anyone would have asked me what the result would be, I'd have said this would not compile because of a variable redefinition, ambiguity or something along those lines. But this totally does compile and crashes on runtime with the previously mentioned Heap Corruption error.
Can anyone explain why does it compile and, when it crashes, it crashes as a heap corruption error instead of a stack [whatever] error? Why the heap and not the stack? I already solved the issue (it builds ok, and runs ok) but I couldn't explain why it behaves like this instead of what I would've expected (compilation error and, if that's wrong, I would have expected it to be a stack error, not Heap)
We expect code to be bad, because we are playing around with Qt right now, so we are not paying any attention to its quality. Please disregard it (unless you believe it's part of the issue at hand, in that case please do point it out as much as you need, haha).
Our environment: Qt 4.8.2, VS2010, Windows 7 x64.
this is the .h
#include <QtGui\QWidget>
#include <QtGui\QLabel>
#include <QtGui\QHBoxLayout>
#include <QtGui\QVBoxLayout>
#include <QtGui\QGridLayout>
#include <QtGui\QFrame>
class Quiniela : public QWidget
{
private:
QLabel m_Fecha;
QLabel m_Titulo;
QLabel m_Hora;
QHBoxLayout m_HeaderLayout;
QFrame m_FrameHeader;
QHBoxLayout m_SorteosLayout;
QHBoxLayout m_EntesLayout;
QGridLayout m_MainLayout;
public:
Quiniela(int w = 800, int h = 600,QWidget* parent = 0);
~Quiniela();
};
and this is the .cpp
#include "Quiniela.h"
#include "FramePrincipal.h"
#include "Utils.h"
Quiniela::Quiniela(int w, int h, QWidget * parent)
: QWidget(parent)
{
Utils objUtil;
QFont fontHead("Arial", 24, QFont::Black);
QFont fontSorteos("Arial", 20, QFont::Normal);
resize(w,h);
setWindowTitle("QUINIELA");
QFrame m_FrameHeader(this);
m_FrameHeader.setGeometry(0,0,800,50);
m_Fecha.setText(objUtil.getDate());
m_Fecha.setFont(fontHead);
m_Titulo.setText("*** QUINIELA ***");
m_Titulo.setFont(fontHead);
m_Hora.setText(objUtil.getTime());
m_Hora.setFont(fontHead);
m_HeaderLayout.addWidget(&m_Fecha,0,Qt::AlignLeft);
m_HeaderLayout.addWidget(&m_Titulo,0,Qt::AlignCenter);
m_HeaderLayout.addWidget(&m_Hora,0,Qt::AlignRight);
m_HeaderLayout.setAlignment(Qt::AlignTop);
m_FrameHeader.setLayout(&m_HeaderLayout);
}
Quiniela::~Quiniela()
{
}

You have to use pointers for Qt objects (Qt maintains parent-child link for its objects via pointers, and destroys children on parent delete). In your example m_FrameHeader is destroyed as constructor returns, since it's declared as a local variable.

There's no compiler error because QFrame m_FrameHeader(this) declares a new (local) variable called m_FrameHeader. This should generate a warning from the compiler that you're hiding the class variable of the same name. Are you sure it didn't? Anyway, the crash happens because m_FrameHeader is destroyed once the constructor returns, yet it is still referenced by things that aren't destroyed. Such as m_HeaderLayout.

Your problem is deletion of objects that are not directly allocated on the heap.
Initially, the widgets you put within Quiniela class are parentless.
Eventually you install them in the m_headerLayout layout, and they will be reparented to the widget that you set the layout on.
The line m_FrameHeader.setLayout(&m_HeaderLayout) sets the parent of m_Fecha, m_Titulo and m_Hora to m_FrameHeader.
Now notice that m_FrameHeader is a local, stack-allocated variable that you defined in the line QFrame m_FrameHeader(this). It goes out of scope at the end of Quiniela constructor. When a QObject with children is destroyed, it will invoke delete on all of the children. Yet those children, specifically m_Fecha, m_Titulo and m_Hora have not been allocated on the heap using new.
Even if you fix the mistake of hiding the class member m_FrameHeader, you still won't fix the crash. It will be merely delayed until the destruction of the instance of Quiniela.
The only way to fix it is to allocate all the widgets on the heap. Your widget should look like this:
class Quiniela : public QWidget
{
private:
QLabel * m_Fecha;
QLabel * m_Titulo;
QLabel * m_Hora;
QHBoxLayout * m_HeaderLayout;
QFrame * m_FrameHeader;
QHBoxLayout * m_SorteosLayout;
QHBoxLayout * m_EntesLayout;
QGridLayout * m_MainLayout;
...
};
You do not need to delete any of those objects explicitly. Qt will do it for you, since they will end up being reparented to the Quiniela widget instance.

Related

How to release memory?

I have Created a simple QT application for my university assignment. What i have done is pop up a new QManinWindow from a Above QMainWindow. When i click a button from the main ui it will pop up a new QMainWindow object (Note Pad)
Note pad is also a QMainWindow object
My Problem is when I'm creating the object it takes some memory from the ram but when I'm closing it (pop up window) memory is not releasing. When each time I'm pressing a button memory is allocated but application does not relese the memory when im closing it. Please check the main screen of the app.
i just want to know how to release that memory. I have tried so many things but nothing worked well.
I have set the closeEvent public on NotePad class and I listen the close event from main object when its get triggered i have deleted the poped up object. But it cause ad unexpected stop.
void MainWindow::on_notePadBtn_clicked()
{
NotePad *notePad = new NotePad(this);
notePad->raise();
notePad->activateWindow();
notePad->show();
}
NotePad::NotePad(QWidget *parent) :QMainWindow(parent),ui(new Ui::NotePad) {
ui->setupUi(this);
this->setWindowTitle("Note Pad");
}
You don't really need to override closeEvent, Qt has Qt::WA_DeleteOnClose attribute, that does exactly what you want, you can use it like this:
//...
NotePad *notePad = new NotePad(this);
notePad->setAttribute(Qt::WA_DeleteOnClose);
notePad->raise();
notePad->activateWindow();
notePad->show();
//...
I'm not familiar with Qt.
But to my understanding if you use the operator new
you must use delete (in a scope where you have access to the pointer created with new).
Object *foo = new Object();
// Do stuff with foo...
delete foo;
// DO NOT use foo from now on.
Hope that helps a bit, maybe. Like I said I'm not familiar with Qt
so if you have doubts about how some features are implemented you should look at the their docs.
(cf: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf §3.7.4p63)

Deleting Pointer to widget Qt C++

I am new with Qt and i am very confused about how widgets are deleted. I was reading a video and i wanted to show up a QProgressbar while the video frames are being read and then remove this QProgressbar when the video is loaded.
I have done it with 2 different ways:
Using Pointers
QWidget* wd = new QWidget();
QProgressBar* pB = new QProgressBar(wd);
QLabel* label = new QLabel(wd);
//setting geometry and updating the label and progressbar
wd->deleteLater();
wd->hide();
this code is written inside a class and i was assuming when the destructor of this class is called, the widget will be deleted with all of it's children but that didn't happen and everytime i run this function again a new widget is created without hiding or deleting the previous one (NOTE: i have tried to delete the label and progressbar from the widget assuming that they will disappear from inside the widget but this didn't happen "delete(pB);")
Using Objects
QWidget wd;
QProgressBar pB(&wd);
QLabel label(wd);
//setting geometry and updating the label and progressbar
wd.deleteLater();
wd.hide();
When i have run the same code but using objects instead of pointers , it has run exactly as i have wanted and everytime i run the function, the old widget is destroyed and a new one is created.
NOTE: -Also when i close the main window, in case of pointers, the widget wd still exists and the program doesn't terminate until i close them manually
- In case of Objects, when i close the main window everything is closed and the program is terminated correctly.
I need someone to explain me why is this happening and how if i am having a vector of pointers to widgets to delete all pointers inside that vector without any memory leakage
In typical C++ the rule would be "write one delete for every new". An even more advanced rule would be "probably don't write new or delete and bury that in the RIAA pattern instead". Qt changes the rule in this regard because it introduces its own memory management paradigm. It's based on parent/child relationships. QWidgets that are newed can be given a parentWidget(). When the parentWidget() is destroyed, all of its children will be destroyed. Hence, in Qt it is common practice to allocate objects on the stack with new, give them a parent, and never delete the memory yourself. The rules get more complicated with QLayout and such becomes sometimes Qt objects take ownership of widgets and sometimes they don't.
In your case, you probably don't need the deleteLater call. That posts a message to Qt's internal event loop. The message says, "Delete me when you get a chance!" If you want the class to manage wd just give it a parent of this. Then the whole parent/child tree will get deleted when your class is deleted.
It's all really simple. QObject-derived classes are just like any other C++ class, with one exception: if a QObject has children, it will delete the children in its destructor. Keep in mind that QWidget is-a QObject. If you have an instance allocated usingnew`, you must delete it, or ensure that something (a smart pointer!) does.
Of course, attempting to delete something you didn't dynamically allocate is an error, thus:
If you don't dynamically allocate a QObject, don't deleteLater or delete it.
If you don't dynamically allocate a QObject's children, make sure they are gone before the object gets destructed.
Also, don't hide widgets you're about to destruct. It's pointless.
To manage widget lifetime yourself, you should use smart pointers:
class MyClass {
QScopedPointer<QWidget> m_widget;
public:
MyClass() :
widget{new QWidget};
{
auto wd = m_widget->data();
auto pb = new QProgressBar{wd};
auto label = new QLabel{wd};
}
};
When you destroy MyClass, the scoped pointer's destructor will delete the widget instance, and its QObject::~QObject destructor will delete its children.
Of course, none of this is necessary: you should simply create the objects as direct members of the class:
class MyClass {
// The order of declaration has meaning! Parents must precede children.
QWidget m_widget;
QProgressBar m_bar{&m_widget};
QLabel m_label{&m_widget};
public:
MyClass() {}
};
Normally you'd be using a layout for the child widgets:
class MyClass {
QWidget m_widget;
QVBoxLayout m_layout{&m_widget};
QProgressBar m_bar;
QLabel m_label;
public:
MyClass() {
m_layout.addWidget(&m_bar);
m_layout.addWidget(&m_label);
}
};
When you add widgets to the layout, it reparents them to the widget the layout has been set on.
The compiler-generated destructor looks as below. You can't write such code, since the compiler-generated code will double-destroy the already destroyed objects, but let's pretend you could.
MyClass::~MyClass() {
m_label.~QLabel();
m_bar.~QProgressBar();
m_layout.~QVBoxLayout();
// At this point m_widget has no children and its `~QObject()` destructor
// won't perform any child deletions.
m_widget.~QWidget();
}

There's a widget declaration order to follow?

Is there a order to declare widgets in Qt5(perhaps 4 too) ?
Consider the following pieces of code:
(just the a piece of the header to help me explain)
class ConfigDialog : public QDialog
{
Q_OBJECT
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
QLabel userLabel;
QLabel passLabel;
QLineEdit userEdit;
QLineEdit passEdit;
};
this works as expected but just changing to (reordering declarations):
class ConfigDialog : public QDialog
{
Q_OBJECT
QLabel userLabel;
QLabel passLabel;
QLineEdit userEdit;
QLineEdit passEdit;
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
};
this works also, but when the ConfigDialog goes out of scope happen a segfault.
I've saw this on other scenarios too, but always changing the order fix this.
My guess would be: you make your QGroupBox a parent of some of the other widgets.
Qt has a concept of parent-child relationship between QObjects. The parent is responsible for deleting its children when it itself is destroyed; it is assumed that those children were allocated on the heap with new.
Further, data members of a C++ class are constructed in the order they are listed in the class, and are destroyed in the reverse order.
Let's say userAuthBox is made a parent of userLabel (via setParent call, in your case executed by addWidget). In the first case, userLabel is destroyed first, and notifies its parent of this fact, whereupon userAuthBox removes it from its list of child widgets, and doesn't attempt to delete it.
In the second case, userAuthBox is destroyed first, and uses delete on its pointer to userLabel. But of course userLabel was not in fact allocated with new. The program then exhibits undefined behavior.
TL;DR: Yes! The order of declarations has a strictly defined meaning in C++. A random order will not work, as you've happened to notice.
You're not showing all the code. What is important is that one of the widgets is a child of the group box. Suppose you had:
class ConfigDialog : public QDialog
{
// WRONG
Q_OBJECT
QLabel userLabel;
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
public:
ConfigDialog(QWidget * parent = 0) :
QDialog(parent),
dialogLayout(this),
userAuthLayout(&userAuthBox) {
// Here userLabel is parent-less.
Q_ASSERT(! userLabel.parent());
userAuthLayout.addWidget(&userLabel, 0, 0);
// But here userLabel is a child of userAuthBox
Q_ASSERT(userLabel.parent() == &userAuthBox);
}
};
The default destructor will invoke the destructors in the following order - it literally is as if you wrote the following valid C++ code in the destructor.
dialogLayout.~QVBoxLayout() - OK. At this point, the dialog is simply layout-less. All the child widgets remain.
userAuthLayout.~QGridLayout() - OK. At this point, the group box is simply layout-less. All the child widgets remain.
userAuthBox.~QGroupBox() - oops. Since userLabel is a child of this object, the nested userAuthox.~QObject call will execute the eqivalent of the following line:
delete &userLabel;
Since userLabel was never allocated using new, you get undefined behavior and, in your case, a crash.
Instead, you should:
Declare child widgets and QObjects after their parents.
Use C++11 value initialization if possible, or initializer lists in the constructor to indicate to the maintainer that there is a dependency between the children and the parents.
See this answer for details and a C++11 and C++98 solution that will force the mistakes to be caught by all popular modern static C++ code analyzers. Use them if you can.

Qt QListWidget addItem memory leak

I have a QComboBox_1 with items added (both icon and text). Then i added item to the QListWidget_1 as below from a QPushButton_1 clicked(). The QListWidget forcing to add a QListWidgetItem as a pointer value.
void MainWindow::on_QPushButton_1_clicked(){
int intSelected = ui->QComboBox_1->currentIndex();
QListWidgetItem *Itm = new QListWidgetItem(ui->QComboBox_1->itemIcon(intSelected), ui->QComboBox_1->itemText(intSelected));
ui->QListWidget_1->addItem(Itm);}
And it is working fine. But i didn't delete the pointer variable "*Itm" in any of the code (MainWindow unload or close). This will create memory leak?
I am a beginner to Qt and C++
Thanks in advance.
No it will not. Technically it's not entirely obvious from the manual, though one definitely can suppose that.
Additionally, in the source of QListWidget.cpp you can see that items are stored inside internal QListModel class which handles deletion of them automatically in its destructor and in other cases when they are removed.

QGraphicsView shows nothing

I'm still learning Qt, I did a little project in Qt, i create a simple ui using qt ui designer, and using QGraphicsView to display a image loaded by QFileDialog, but when I added loaded image file to QgraphicsScene, the image is not displayed in the graphicview. The graphicView stay blank, please help me, thanks !
Project2::Project2(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui = new Ui::Project2Class;
ui->setupUi(this);
this->scene = new QGraphicsScene;
this->scene->setSceneRect(0, 0, 649, 459);
connect(ui->mapLoaderButton, SIGNAL(clicked()), this, SLOT(GetfilePath()));
ui->graphicsView->setScene(this->scene);
}
void Project2::GetfilePath()
{
QString filePath = QFileDialog::getOpenFileName(this, tr("Select file"), "", tr("Files (*.jpg*)"));
if (filePath.isNull() == false)
{
QImage image(filePath);
QSize size = image.size();
ui->graphicsView->scene()->addItem(&QGraphicsPixmapItem(QPixmap::fromImage(image)));
ui->graphicsView->scene()->update();
ui->graphicsView->viewport()->update();
}}
QGraphicsScene, and most of Qt, takes ownership of the variable. The variable should be dynamically allocated.
Variables created on the stack won't work, because their lifetimes are too short and the QObject will later try and delete them.
You need to create your QGraphicsPixmapItem with 'new'.
ui->graphicsView->scene()->addItem(new QGraphicsPixmapItem(QPixmap::fromImage(image)));
Everything that inherits from QObject can own (and be owned by) other QObject classes. When a QObject is destroyed, it calls 'delete' on all its children. QObject classes want to 'own' their children. By 'own' I mean control the lifetimes of.
In your case, you were creating the QObject (QGraphicsPixmapItem) on the stack. It's lifetime is then controlled by the stack (but the QObject thinks it's controlling it), and the stack will delete it by the time it reaches the semi-colon of that 'addItem()' function-call.
As a general C++ rule-of-thumb, if a function is asking for a pointer, don't give it a temporary (unnamed) object.
As a general Qt rule-of-thumb, if a function is asking for a pointer, don't even given it a named local-variable - most want a dynamically allocated variable, so look the function up on the documentation and see if it mentions 'taking ownership'. If so, 'new' it and let Qt later 'delete' it.