Solved The program has unexpectedly finished.
-
I have a very simple program that finds the intersection of two QLineF and draws a circle around the intersection point. It will compile , but when I try to run it I get the message "The program has unexpectedly finished." and the window closes. The very strange thing is that if I try running the program again and again I will work, sometime on the third try or fifth try. Has any one seen this. It is Qt5.9 on a 64-bit Mint Linux.
I can post the program if that is required. Any ideas?
Thanks
-
@ofmrew Let me add that when it works it fails when I move the mouse. Does that help?
-
I reopened this because I am at an impasse. I ran example2 in debug mode and got to the end; however, in normal run it just exits.
#ifndef MYCANVAS_H
#define MYCANVAS_H#include <QWidget>
#include <QPainter>
#include <QLineF>class MyCanvas : public QWidget
{
Q_OBJECT
public:
explicit MyCanvas(QWidget *parent = nullptr);
void paintEvent(QPaintEvent *e);int exampleType; QLineF lineA; QLineF lineB; QLineF line0; QLineF line1; QLineF line2; QLineF line3; QLineF line4; QLineF line5; QVector<QLineF> poly; QPointF *intersectionPointA; QLineF::IntersectType intersectionTypeA; QPointF *intersectionPoint; QPointF *intersectionPointPoly; QLineF::IntersectType intersectionType;
signals:
public slots:
void intersectionExample1();
void intersectionExample2();};
#endif // MYCANVAS_H
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->canvas->setBackgroundRole(QPalette::Base);
connect(ui->example1, &QPushButton::clicked, ui->canvas, &MyCanvas::intersectionExample1);
connect(ui->example2, &QPushButton::clicked, ui->canvas, &MyCanvas::intersectionExample2);
}#include "mycanvas.h"
#include <QDebug>MyCanvas::MyCanvas(QWidget *parent) : QWidget(parent)
{}
void MyCanvas::paintEvent(QPaintEvent *e)
{
QPainter p(this);
if (exampleType == 1){
qDebug() << " In PaintEvent" << *intersectionPointA;
p.drawLine(lineA);
p.drawLine(lineB);
if (intersectionTypeA == QLineF::BoundedIntersection){
p.drawEllipse(*intersectionPointA, 5, 5);
}
return;
}
if (exampleType == 2){
qDebug() << " In 2";
p.drawLine(line0);
p.setPen(QColor(Qt::red));
p.drawLines(poly);
p.drawEllipse(*intersectionPointPoly, 5, 5);
return;
}
}void MyCanvas::intersectionExample1()
{
exampleType = 1;
lineA = QLineF(QPointF(0.0, 0.0), QPointF(600.0, 800.0));
lineB = QLineF(QPointF(500.0, 100.0), QPointF(100.0, 500.0));
qDebug() << line1 << " " << line2;
intersectionTypeA = lineA.intersect(lineB, intersectionPointA);
qDebug() << intersectionTypeA << " " << *intersectionPointA << " Got Past Intersection";
this->update();
return;
}void MyCanvas::intersectionExample2()
{
exampleType = 2;
line0 = QLineF(QPointF(100.0, 100.0), QPointF(500.0, 500.0));line1 = QLineF(QPointF(500.0, 100.0), QPointF(450.0, 250.0)); line2 = QLineF(QPointF(450.0, 250.0), QPointF(325.0, 300.0)); line3 = QLineF(QPointF(325.0, 300.0), QPointF(250.0, 300.0)); line4 = QLineF(QPointF(250.0, 300.0), QPointF(200.0, 250.0)); line5 = QLineF(QPointF(200.0, 250.0), QPointF(100.0, 150.0)); poly << line5 << line4 << line3 << line2 << line1; qDebug() << poly; for (int i = 0; i < poly.count(); i++){ QLineF l = poly.at(i); qDebug() << i << " " << line0 << " " << l; intersectionType = line0.intersect(l, intersectionPoint); qDebug() << i << intersectionType; //<< " " << *intersectionPoint; if (intersectionType == QLineF::BoundedIntersection){ qDebug() << "In if";// << *intersectionPoint; intersectionPointPoly = new QPointF(*intersectionPoint); qDebug() << " Past new"; //qDebug() << i << " " << intersectionType << " " << *intersectionPoint; } } this->update();
}
It is probably something stupid, but I do not see the problem. Any help will be greatly appreciated.
Thanks
-
Hi,
Why are you using pointers for these QPoint variables ?
From a quick look, you didn't initialyse them.
-
QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const.
I set them up as instance variables (data members) so I could assign a values in one method without having them lost before they could be used in paintEvent().
If the is a better way I am open to suggestions.
-
class MyCanvas : public QWidget { Q_OBJECT public: explicit MyCanvas(QWidget *parent = nullptr); void paintEvent(QPaintEvent *e); int exampleType; QLineF lineA; QLineF lineB; QLineF line0; QLineF line1; QLineF line2; QLineF line3; QLineF line4; QLineF line5; QVector<QLineF> poly; QPointF *intersectionPointA; QLineF::IntersectType intersectionTypeA; QPointF *intersectionPoint; QPointF *intersectionPointPoly; QLineF::IntersectType intersectionType;
What @SGaist means: why are intersectionPointA, intersectionPoint, intersectionPointPoly pointers? Just do them normal instance variables. Nothing will be lost.
QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const.
What is the problem with that? Just get pointers to your instance variables if you call it:
point::intersect(line, &intersectionPoint);
-
@jsulm
I changed the three pointer variables as suggested and it worked. Also, I prefer not using pointers unless absolutely necessary. There is, however, something that that change does not explain; namely, why after some number of failures it just worked. I know the trick of deleting the build directory, is this something of that nature? I hate inconsistency: a program should produce the same result every time it is executed with the same input. That is why the trick with the build library bothers me.I wrote a closest point on a line segment to a point method which returned a structure that contained three variables; whether it was valid based on a distance parameter, whether it was an end point of the segment and the point. That seems a much nicer way to handle something like the line segments intersection. But that is me.
Thanks to both.
-
@ofmrew said in The program has unexpectedly finished.:
a program should produce the same result every time it is executed with the same input.
Not true if you have undefined behaviour. Usually this translates in "the state of your RAM is an input" and the state of your RAM is (almost) never the same when you run the program again
-
@VRonin
I agree that RAM is inconsistent (except with some old systems that zeroed memory when a program was loaded), but a correct program never depends of the state of uninitialized memory. Are you saying that Qt caches some program data memory and reuses it or was it because I allocated the pointer but did not initialize the object to which it pointed? C++ and Qt do a lot "stuff" under the covers and I what to learn what not to do. -
@ofmrew said in The program has unexpectedly finished.:
but a correct program never depends of the state of uninitialized memory
You exactly got the point there. A correct program never does. A program that uses dangling pointers (as yours above) does, by definition, depend of the state of uninitialized memory
-
@VRonin
Question. If I define a pointer variable, but never use it ( assignment or reference) why would it cause a problem? The definition should only allocate the memory for the pointer. I believe that it was in one of my qDebug statements that caused the problem, adding the example 2 code. I got misled by the method using a pointer and down a lot of rabbit holes. Thanks. -
I think the confusion is arising from how Qt handles output arguments. To highlight the fact that certain arguments will be changed internally by the function, Qt uses pointer arguments instead of non-const references. It's a (wise imho) implementation choice. The second argument to
QLineF::intersect
is one of these cases. You can check here what the function is doing with theintersectionPoint
argument. It's assigning to it.So passing a dangling pointer to that method (as you are) is equivalent to assigning to it
-
@VRonin
ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"I find it interesting that this comes from the same set of books I used extensively in the early 1990 and probably used this routine. (I was developing an object oriented GIS-Facilities Manage System for utilities using Smalltalk that was base on interactive graphics, when most graphics systems were batch. In did interactively what others did with a clean and build. I worked extremely well on a 386 machine running OS/2.)
Are all the Qt classes on that web site? It does as I thought that it would by assigning the value. Again, my mistake was an errant qDebug using the dangling pointer. I need to go back to the C++ literature to look at assignment. Is it a replacement of pointers or is it copying the variables of the new point replacing the existing ones--which would be a problem if the pointer was not initialized.