Results 1 to 7 of 7

Thread: QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

  1. #1
    Join Date
    May 2014
    Posts
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

    Hallo,

    if I create an path object (class Path : public QObject, public QGraphicsPathItem) in an other std::thread then his parent item (class Anchor : public QObject, public QGraphicsPixmapItem), it crashes.
    The funny thing is, that it doesn't crashes if the QMainWindow that holds the QGraphicScene has no parent. If it's parent is a QTabWidget it crashes.


    Anchor.cpp
    Qt Code:
    1. void Anchor::addDistanceValue(double distanceValue) {
    2. mutex.lock();
    3. bool stillWorking = isWorking;
    4. mutex.unlock();
    5. if(!stillWorking){
    6. mutex.lock();
    7. isWorking = true;
    8. mutex.unlock();
    9. if (wallCheckerThread.joinable()){
    10. //QTime timeStamp = QTime::currentTime();
    11. wallCheckerThread.join();
    12. //qDebug() << "wait to join anker: " << id << "in " << timeStamp.msecsTo(QTime::currentTime()) << "ms";
    13. }
    14.  
    15.  
    16.  
    17. wallCheckerThread = std::thread([&](double distanceValue){
    18.  
    19. QTime timeStamp = QTime::currentTime();
    20.  
    21. classMutex.lock();
    22. mutex.lock();
    23. Path* item = new Path(distanceValue * 100, this); // <<--- here is the problem, the this
    24. mutex.unlock();
    25. //item->setPos(pos());
    26. item->setVisible(false);
    27. //scene()->addItem(item);
    28. classMutex.unlock();
    29.  
    30.  
    31. checkAdditionalPathLossChanges(distanceValue, item);
    32.  
    33. qDebug() << "Anker " << getId() << ": " << timeStamp.msecsTo(QTime::currentTime()) << "ms";
    34.  
    35. QPen pen;
    36. pen.setColor(0x8888ff);
    37. item->setPen(pen);
    38. item->setFlags(0);
    39. item->setAcceptedMouseButtons(Qt::NoButton);
    40.  
    41. distanceVector.push_back(distanceValue);
    42.  
    43. ellipses.append(item);
    44.  
    45. if (distanceVector.length() > 1){
    46. distanceVector.pop_front();
    47.  
    48. classMutex.lock();
    49. delete ellipses.first();
    50. //scene()->removeItem(ellipses.first());
    51. classMutex.unlock();
    52.  
    53. if (!ellipses.isEmpty())
    54. ellipses.pop_front();
    55. }
    56. item->setVisible(true);
    57. mutex.lock();
    58. isWorking = false;
    59. mutex.unlock();
    60. }, distanceValue);
    61. }else{
    62. qDebug() << "skipped anker " << id;
    63. }
    64. }
    To copy to clipboard, switch view to plain text mode 

    path.h
    Qt Code:
    1. #include <QGraphicsItem>
    2. #include <QObject>
    3. #include <QGraphicsSceneMouseEvent>
    4.  
    5. class Path : public QObject, public QGraphicsPathItem
    6. {
    7. Q_OBJECT
    8. Q_INTERFACES(QGraphicsItem)
    9.  
    10. public:
    11. explicit Path(qreal radius, QGraphicsItem *parent = 0):
    12. QGraphicsPathItem(parent) // << here it crashes (path.h 15)
    13. {
    14. myPath = new QPainterPath();
    15. myPath->addEllipse(QRectF(-radius,-radius,radius * 2, radius * 2));
    16. setPath(*myPath);
    17. setZValue(1);
    18. }
    19.  
    20. enum { Type = UserType + 3 };
    21.  
    22. int type() const { return Type; }
    23. void addPainterPath(QPainterPath path){ *myPath += path; setPath(*myPath);}
    24. QPainterPath* getPainterPath() {return myPath; }
    25.  
    26. protected:
    27. // QGraphicsEllipseItem *item;
    28. void mousePressEvent(QGraphicsSceneMouseEvent *event){
    29. QGraphicsPathItem::mousePressEvent(event);
    30. }
    31.  
    32. void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
    33. QGraphicsPathItem::mouseMoveEvent(event);
    34. }
    35. QPainterPath *myPath;
    36. };
    To copy to clipboard, switch view to plain text mode 

    working if its used this way:

    Qt Code:
    1. #include <QApplication>
    2. #include <QFile>
    3. #include <QObject>
    4. #include <QDebug>
    5. #include "serialwidget.h"
    6. #include "radarwidget.h"
    7.  
    8. int main(int argc, char *argv[])
    9. {
    10. QApplication app(argc, argv);
    11. RadarWidget radarWidget;
    12. radarWidget.show();
    13. SerialWidget mainWindow;
    14. mainWindow.show();
    15. QObject::connect(&mainWindow, SIGNAL(newDistanceData(int, double)), &radarWidget, SLOT(addNodeDistance(int, double)));
    16. radarWidget.setSettingsProvider(mainWindow.getSettingsProvider());
    17. return app.exec();
    18.  
    19.  
    20. ////////////////////////
    21.  
    22. just as additional info:
    23. the signal is passed to the right anchor
    24.  
    25.  
    26. void RadarGraphicsView::addNodeDistance(int id, double distance){
    27. if(anchors.length() == 0){
    28. QTimer *timer = new QTimer(this);
    29. connect(timer, SIGNAL(timeout()), this, SLOT(calculateLocation()));
    30. timer->start(1000);
    31. QThread::msleep(20);
    32. }
    33.  
    34. for(int i = 0; i < anchors.length(); i++){
    35. if(anchors.at(i)->getId() == id){
    36. anchors.at(i)->addDistanceValue(distance);
    37. anchors.at(i)->update();
    38. this->scene()->update();
    39. return;
    40. }
    41. }
    42. Anchor::classMutex.lock();
    43. Anchor *newAnchor = new Anchor(id);
    44. this->scene()->addItem(newAnchor);
    45. Anchor::classMutex.unlock();
    46. double x = settings->getSetting(id, "x");
    47. double y = settings->getSetting(id, "y");
    48. newAnchor->setPos(x,y);
    49. newAnchor->addDistanceValue(distance);
    50. anchors.append(newAnchor);
    51. }
    52. ////////////////////////////////////////
    53. }
    To copy to clipboard, switch view to plain text mode 


    it isnt working this way:

    Qt Code:
    1. SerialWidget::SerialWidget(QWidget *parent) :
    2. QMainWindow(parent),
    3. ui(new Ui::SerialWidget)
    4. {
    5. ui->setupUi(this);
    6. Pi = 3.1415;
    7. intValidator = new QIntValidator(0, 3000000, this);
    8. ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert);
    9. connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)), this, SLOT(showPortInfo(int)));
    10. connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)), this, SLOT(checkCustomBaudRatePolicy(int)));
    11. //connect(ui->actionSaveMeasurement, SIGNAL(triggered())
    12. //connect(ui->localEchoCheckBox, SIGNAL(clicked(bool)), ui->console, SLOT(setLocalEchoEnabled(bool)));
    13. fillPortsParameters();
    14. fillPortsInfo();
    15. updateSettings();
    16. this->showMaximized();
    17. deviceData.clear();
    18.  
    19. replayTool = new ReplayTool();
    20. replayTool->moveToThread(&replayToolThread);
    21. connect(replayTool, SIGNAL(sigDataRecieved(QByteArray)), this, SLOT(readData(QByteArray)));
    22. replayToolThread.start(QThread::LowestPriority);
    23.  
    24. ui->cBDeviceSelector->blockSignals(true);
    25. ui->cBDeviceSelector->insertItem(0,"General Settings");
    26. ui->cBDeviceSelector->blockSignals(false);
    27. ui->cBDeviceSelector->setDuplicatesEnabled(false);
    28. on_friisOkPushButton_clicked();
    29. deviceSettings = new SettingsProvider(&friisDefaultSettings);
    30.  
    31. rssiFilter = new RssiFilter();
    32. isReplayPaused = false;
    33. // if the qmainwindow is a chiild of this object ----------------------|
    34. QObject::connect(this, SIGNAL(newDistanceData(int, double)), ui->sWRadar, SLOT(addNodeDistance(int, double))); // <<--- the radar is a child of the mainwindow
    35. ui->sWRadar->setSettingsProvider(deviceSettings);
    36. }
    To copy to clipboard, switch view to plain text mode 

    the debugger says:

    SIGSEGV
    Segmantation fault


    stack:
    Qt Code:
    1. 0 ?? 0x1d2bf51c
    2. 1 QCoreApplicationPrivate::checkReceiverThread 513 0x6b929693
    3. 2 QApplication::notify 2791 0x91eb4ba
    4. 3 QCoreApplication::notifyInternal 935 0x6b929f96
    5. 4 QCoreApplication::sendEvent 237 0x9536429
    6. 5 QGraphicsScene::setFocus 2969 0x94a835a
    7. 6 QGraphicsScenePrivate::setActivePanelHelper 743 0x94a1c63
    8. 7 QGraphicsScene::setActivePanel 5644 0x94b180c
    9. 8 QGraphicsItem::setActive 3188 0x94813fc
    10. 9 QGraphicsItemPrivate::setParentItemHelper 1222 0x947b90a
    11. 10 QGraphicsItem::setParentItem 1685 0x947ce1b
    12. 11 QGraphicsItem::QGraphicsItem 1399 0x947c412
    13. 14 Path::Path path.h 15 0x43010a
    14. 15 Anchor::__lambda2::operator() anchor.cpp 364 0x40f3cb
    15. 16 std::_Bind_simple<Anchor::addDistanceValue(double)::__lambda2(double)>::_M_invoke<0u>(std::_Index_tuple<0u>) functional 1732 0x41184f
    16. 17 std::_Bind_simple<Anchor::addDistanceValue(double)::__lambda2(double)>::operator()(void) functional 1720 0x41173c
    17. 18 std::thread::_Impl<std::_Bind_simple<Anchor::addDistanceValue(double)::__lambda2(double)> >::_M_run(void) thread 115 0x4116a4
    18. 19 libstdc++-6!execute_native_thread_routine C:\Qt\5.3\mingw482_32\bin\libstdc++-6.dll 0xffe58f
    19. 20 pthread_create_wrapper C:\Qt\Tools\mingw482_32\opt\bin\libwinpthread-1.dll 0x64944e4b
    20. 21 wtoi64 C:\Windows\SysWOW64\msvcrt.dll 0x759c0bc4
    21. 22 msvcrt!_beginthreadex C:\Windows\SysWOW64\msvcrt.dll 0x759c0cec
    22. 23 KERNEL32!BaseThreadInitThunk C:\Windows\SysWOW64\kernel32.dll 0x75e5919f
    23. 24 ntdll!RtlInitializeExceptionChain C:\Windows\SYSTEM32\ntdll.dll 0x77e8a8cb
    24. 25 ntdll!RtlInitializeExceptionChain C:\Windows\SYSTEM32\ntdll.dll 0x77e8a8a1
    25. 26 ??
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,479
    Thanks
    252
    Thanked 709 Times in 699 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

    All GUI objects have to be owned by the main application thread. They can't be created or parented by object instances that live in other threads.

  3. #3
    Join Date
    May 2014
    Posts
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

    Thats not 100% true. Like I wrote it is working in Qt 5.2.1 and it is created in an other std::thread but not owned. The parent was created in the main GUI thread and the std::thread only manipulate attributes, it does not draw, interact on or with the GUI.

    This is a minimal example. compile it as debug and it crashes, compile it as release and it works.

    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QMainWindow>
    5. #include <thread>
    6. #include <QGraphicsPathItem>
    7.  
    8. namespace Ui {
    9. class MainWindow;
    10. }
    11.  
    12. class MainWindow : public QMainWindow
    13. {
    14. Q_OBJECT
    15.  
    16. public:
    17. explicit MainWindow(QWidget *parent = 0);
    18. ~MainWindow();
    19.  
    20. private:
    21. Ui::MainWindow *ui;
    22.  
    23. bool init;
    24. std::thread otherThread;
    25. QGraphicsPathItem *itemParent;
    26.  
    27. private slots:
    28. void on_pushButton_clicked();
    29. };
    30.  
    31. #endif // MAINWINDOW_H
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3. #include <QGraphicsPixmapItem>
    4. #include <QGraphicsView>
    5.  
    6. MainWindow::MainWindow(QWidget *parent) :
    7. QMainWindow(parent),
    8. ui(new Ui::MainWindow)
    9. {
    10. ui->setupUi(this);
    11.  
    12. QGraphicsScene *scene = new QGraphicsScene(this);
    13. scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    14. ui->graphicsView->setScene(scene);
    15. scene->setSceneRect(0, 0, 100, 100);
    16.  
    17. //scene->setSceneRect(scene->sceneRect() + QMarginsF(100,100,100,100));
    18. //scene->setSceneRect(-width/2, hight/2, width/2, hight/2);
    19. ui->graphicsView->setCacheMode(QGraphicsView::CacheBackground);
    20. ui->graphicsView->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
    21. ui->graphicsView->setRenderHint(QPainter::Antialiasing);
    22. ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    23. ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    24. ui->graphicsView->setUpdatesEnabled(true);
    25.  
    26. init = false;
    27. }
    28.  
    29. MainWindow::~MainWindow()
    30. {
    31. if(otherThread.joinable()) otherThread.join();
    32. delete ui;
    33. }
    34.  
    35. void MainWindow::on_pushButton_clicked()
    36. {
    37. if(init == false){
    38. init = true;
    39. path.addEllipse(QRectF(-10,-10,10 * 2, 10 * 2));
    40. itemParent = new QGraphicsPathItem(path);
    41. ui->graphicsView->scene()->addItem(itemParent);
    42.  
    43. }else{
    44. if(otherThread.joinable()){
    45. otherThread.join();
    46. }
    47. otherThread = std::thread([&](){
    48. path.addRect(-10,-10,20,20);
    49. QGraphicsPathItem *child = new QGraphicsPathItem(path, itemParent);
    50. });
    51. }
    52. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by lexxxel; 21st May 2014 at 12:11.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,479
    Thanks
    252
    Thanked 709 Times in 699 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

    This is a minimal example. compile it as debug and it crashes, compile it as release and it works.
    This is never a test for valid code, and in fact is a clear signal that you're doing something wrong. Memory layout, variable initialization, and many other things are different between debug and release builds, so whatever is happening to corrupt memory or the stack might only happen as result of this difference.

  5. #5
    Join Date
    May 2014
    Posts
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

    That is right. In my program I keep it thread safe with some mutexs. And in my project both debug and release worked when I used Qt 5.2.1

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,479
    Thanks
    252
    Thanked 709 Times in 699 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

    I don't know. I notice you're specifying variable capture [&] in your lambda expression, but you have no variables in the function definition. Don't know if that makes a difference.

    You are creating your child path item in the otherThread, but you are giving it a parent that is owned by the scene in the main thread. I don't think that works. If you implement a signal / slot pair where the thread sends a signal asking for a child pointer, and the child item is created in the slot in the main thread and its pointer passed back to otherThread, that will ensure that all of the GUI items remain owned by the main thread, but can be manipulated by otherThread (with locking, of course).

  7. #7
    Join Date
    May 2014
    Posts
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsPathItem(parent) constructor crashes (SIGSEGV)

    I changed my program. Now i have only one object as a child, which is created in the parentObject constructor. I only change the Path in the otherThread.
    But still something is wrong here. The thread check didn't work correct in my main project, but in the minimal example. I dont know why and I dont have the skill and time to fix it. But maybe someone else....

Similar Threads

  1. Replies: 3
    Last Post: 7th April 2014, 09:43
  2. Dynamic type of parent outside the constructor
    By w4r1o in forum Qt Programming
    Replies: 2
    Last Post: 26th March 2011, 06:30
  3. Program crashes while trying to do a check in constructor
    By hakermania in forum Qt Programming
    Replies: 5
    Last Post: 1st September 2010, 10:15
  4. Replies: 1
    Last Post: 22nd April 2010, 14:34
  5. Program crashes (SIGSEGV)
    By Voldemort in forum Qt Programming
    Replies: 47
    Last Post: 21st May 2007, 20:09

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.