PDA

View Full Version : Program runs fine in Debug mode, but produces segmentation fault in Release Mode



realJohnDoe
7th March 2012, 14:56
Hi Guys,

Im quite new to Qt and have a problem, which i cant figure out how to solve:

My program runs fine in Debug mode (using MingW compiler and Windows 7), but when i try to run it in Release mode, it produces "segmentation fault" errors when i close it or when i try to emit a signal in "NewGameWindow::on_pushButton_clicked()". I already searched on the internet and figured out, it probably has to be a wrong pointer, but i do not really know, what to look for in my code. If i show the stack in Debugging mode, it just shows "??" on every level.

heres my source code:

Go.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2012-02-29T14:20:46
#
#-------------------------------------------------

QT += core gui

TARGET = Go
TEMPLATE = app


SOURCES += main.cpp\
Interface/mainwindow.cpp \
Interface/newgamewindow.cpp \
Model/TwoDGrid.cpp \
Model/TwoDCoord.cpp \
Model/GameLogic.cpp \
Interface/GraphicsView/mouseovercircle.cpp

HEADERS += Interface/mainwindow.h \
Interface/newgamewindow.h \
Model/TwoDGrid.h \
Model/TwoDCoord.h \
Model/GameLogic.h \
Interface/GraphicsView/mouseovercircle.h

FORMS += mainwindow.ui \
newgamewindow.ui

OTHER_FILES += \
Interface/White Stone60.bmp \
Interface/White Circle30.bmp \
Interface/Black Stone60.bmp \
Interface/Black Circle30.bmp

RESOURCES += \
GameImages.qrc


main.cpp:

#include <QtGui/QApplication>
#include "Interface/mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

MainWindow MainWdw;
MainWdw.resize(700, 700);
MainWdw.show();

return a.exec();
}


mainwindow.cpp:

#include "Interface/mainwindow.h"
#include "ui_mainwindow.h"
#include "Interface/newgamewindow.h"
#include "Model/GameLogic.h"

#include <QtGui>
#include <QLabel>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
ui->graphicsView->setSceneRect(-300, -300, 600, 600);
ui->graphicsView->setRenderHint(QPainter::Antialiasing);
ui->graphicsView->setBackgroundBrush(QPixmap(":/Background600pattern.jpg"));

connect(&theGameLogic, SIGNAL(FieldChangedOut(int,int,int)), this, SLOT(FieldChanged(int,int,int)));
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_actionNew_Game_triggered()
{
NewGameWindow NewGameWdw(this);
connect(&NewGameWdw, SIGNAL(BoardSizeSet(int)), this, SLOT(BoardSizeSet(int)));
connect(&NewGameWdw, SIGNAL(GameStarted()), this, SLOT(GameStarted()));

NewGameWdw.exec();
}
void MainWindow::on_actionExit_triggered()
{
this->close();
}

void MainWindow::BoardSizeSet(int Size)
{
if(!theGameLogic.SetSize(Size))
QMessageBox::warning(this, "Error", "Cannot set size. Game already started!");
else
{
BoardSize = Size;

int LineWidth = 4;
BorderWidth = 30;
GridWidth = (float)(600 - 2 * BorderWidth) / (BoardSize - 1);

QPen LinePen(Qt::black);
LinePen.setWidth(LineWidth);
LinePen.setCapStyle(Qt::SquareCap);

for(int i = 0; i < BoardSize; i++)
{
scene->addLine(BorderWidth - 300 + (i * GridWidth), BorderWidth - 300, BorderWidth - 300 + (i * GridWidth), 300 - BorderWidth, LinePen); //paint vertical lines
scene->addLine(BorderWidth - 300, BorderWidth - 300 + (i * GridWidth), 300 - BorderWidth, BorderWidth - 300 + (i * GridWidth), LinePen); //paint horizontal lines
}
}
}

void MainWindow::GameStarted()
{
if(!theGameLogic.StartGame())
QMessageBox::warning(this, "Error", "Cannot start game. Game already started!");

else
{
// Allocation of Board //

circle = new MouseoverCircle**[ BoardSize ];

for( int Column = 0; Column < BoardSize; Column++ )
{
circle[ Column ] = new MouseoverCircle*[ BoardSize ];

for( int Row = 0; Row < BoardSize; Row++ )
{
circle[ Column ][ Row ] = new MouseoverCircle( Column, Row );
scene->addItem(circle[ Column ][ Row ]);
circle[ Column ][ Row ]->setPos(-300 + BorderWidth + GridWidth * Column, -300 + BorderWidth + GridWidth * Row);
connect(circle[Column][Row], SIGNAL(Mouseover(int,int)), this, SLOT(Mouseover(int,int)));
connect(circle[Column][Row], SIGNAL(Clicked(int,int)), this, SLOT(Clicked(int,int)));
}
}
}
}

void MainWindow::Mouseover(int Column, int Row)
{
switch (theGameLogic.LegalTurn(Column, Row))
{
case 0:
{
circle[Column][Row]->Color = QColor(0, 0, 0, 0);
}
case 1:
{
circle[Column][Row]->Color = QColor(0, 0, 0, 127);
break;
}
case 2:
{
circle[Column][Row]->Color = QColor(255, 255, 255, 127);
break;
}
}
}

void MainWindow::Clicked(int Column, int Row)
{
theGameLogic.ExecuteTurn(Column, Row);
}

void MainWindow::FieldChanged(int Column, int Row, int NewValue)
{
QPen *RPen;
QBrush *RBrush;
switch(NewValue)
{
case 0:
{
RPen = new QPen(QColor(127, 127, 127));
RBrush = new QBrush(QColor(127, 127, 127));
break;
}
case 1:
{
RPen = new QPen(QColor(0, 0, 0));
RBrush = new QBrush(QColor(0, 0, 0));
break;
}
case 2:
{
RPen = new QPen(QColor(255, 255, 255));
RBrush = new QBrush(QColor(255, 255, 255));
break;
}
default:
{
RPen = new QPen(QColor(255, 0, 0));
RBrush = new QBrush(QColor(255, 0, 0));
break;
}
}
scene->addEllipse(-325 + BorderWidth + GridWidth * Column, -325 + BorderWidth + GridWidth * Row, 50, 50, *RPen, *RBrush);
}


newgamewindow.cpp:

#include "Interface/newgamewindow.h"
#include "ui_newgamewindow.h"

#include <QtGui>
#include <QDebug>

NewGameWindow::NewGameWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::NewGameWindow)
{
ui->setupUi(this);
}

NewGameWindow::~NewGameWindow()
{
delete ui;
}

void NewGameWindow::on_pushButton_clicked()
{
if(ui->radioButton->isChecked())
//QMessageBox::information(this, "board size set", "board size set to 9x9");
emit BoardSizeSet(9);
if(ui->radioButton_2->isChecked())
//QMessageBox::information(this, "board size set", "board size set to 13x13");
emit BoardSizeSet(13);
if(ui->radioButton_3->isChecked())
//QMessageBox::information(this, "board size set", "board size set to 19x19");
emit BoardSizeSet(19);
emit GameStarted();
qDebug() << "test";
this->close();
}


if you need further information, just ask. Thank you for your help!

EDIT: I figured out, the segmentation faults were coming from delete-commands in my model. After i removed them from the code, I now get segmentation faults when a mouseover over a circle occurs.

EDIT2: Okay, i removed one line to much, so one pointer was set wront. The problem is now solved.

d_stranz
7th March 2012, 22:34
In your FieldChanged() method, it is not necessary to create new QPen and QBrush instances using "new", since you are passing them as const references into the scene->addEllipse() method. As it stands now, you have a memory leak every time the FieldChanged method is executed because you new up the pen and brush and never delete them..

Simply declare QPen and QBrush instances on the stack and pass them in as is. Rewrite the code as follows:



void MainWindow::FieldChanged(int Column, int Row, int NewValue)
{
QColor penColor;
QColor brushColor;
switch(NewValue)
{
case 0:
{
penColor = QColor(127, 127, 127);
brushColor = QColor(127, 127, 127);
break;
}
case 1:
{
penColor = QColor(0, 0, 0);
brushColor = QColor(0, 0, 0);
break;
}
case 2:
{
penColor = QColor(255, 255, 255);
brushColor = QColor(255, 255, 255);
break;
}
default:
{
penColor = QColor(255, 0, 0);
brushColor = QColor(255, 0, 0);
break;
}
}
scene->addEllipse(-325 + BorderWidth + GridWidth * Column, -325 + BorderWidth + GridWidth * Row, 50, 50, QPen( penColor ), QBrush( brushColor ) );
}


And regarding QWidget (QObject) ownership: As a general rule, any time you new a QObject, then give it to another QObject that will be its parent, the parent takes control of the lifetime of the object and you do not have to call delete on it. Likewise, calling setupUI on an embedded UI pointer passes ownership of that to the widget for which the ui is being created, and the QObject ownership mechanism will take care of deleting the pointer when the widget goes out of scope. Double deletes will cause the crashes you experienced, and it's a clear sign that you either are trying to use a pointer that hasn't been initialized or you're trying to delete one that's already been deleted.

Any other type of pointer (like your own C++ objects) follow the normal C++ rules: if you new it, you must delete it.