Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 3

Qt-interest Archive, April 2008
Very lazy deletion with Qt::WA_DeleteOnClose widget attribute set in Qt 4.2.2


Message 1 in thread

Hi all,

I had a hard time trying to figure out a strange segfault when closing and rebuilding a widget.
It turned out that deletion took place *after* the new widget had been constructed, and affected the *new* widget.
 
The widget had the  Qt::WA_DeleteOnClose attribute so I only called close() on it, without explicit deletion.
It seems that in such case in Qt4 the widget's deletion is delayed and you have absolutely no control upon when it will happen. 
 
It looks like the problem is now solved just by explicitely calling delete.

(Just in case this spares some time to s/o.)

-- 
 [ signature omitted ] 

Message 2 in thread

This is CORRECT behavior....

The delete on close attribute, basically puts a flag on the widget "to
be deleted later"

The actual deletion will occur during the next loop through the event
loop..

This allows any currently pending slot/signal connections to go through
properly and then the item is deleted.

Scott

> -----Original Message-----
> From: Alexandre Oberlin [mailto:alxobr@xxxxxxxxx]
> Sent: Thursday, April 10, 2008 9:21 AM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Very lazy deletion with Qt::WA_DeleteOnClose widget attribute
> set in Qt 4.2.2
> 
> Hi all,
> 
> I had a hard time trying to figure out a strange segfault when closing
> and rebuilding a widget.
> It turned out that deletion took place *after* the new widget had been
> constructed, and affected the *new* widget.
> 
> The widget had the  Qt::WA_DeleteOnClose attribute so I only called
> close() on it, without explicit deletion.
> It seems that in such case in Qt4 the widget's deletion is delayed and
> you have absolutely no control upon when it will happen.
> 
> It looks like the problem is now solved just by explicitely calling
> delete.
> 
> (Just in case this spares some time to s/o.)
> 
> --
> AO
> 
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/

--
 [ signature omitted ] 

Message 3 in thread

Scott Aron Bloom écrivit:
> This is CORRECT behavior....
Sure. But it is annoying when your brand new widget gets deleted ;-)
 
-- 
 [ signature omitted ] 

Message 4 in thread

The only way that would happen is if your new widget sets directly or via a parent path, its parent pointer to the recently closed widget...

Which is a logic mistake on your part.... 

My question, if you have a widget that is being recreated... why mark it as being deleted on close

Scott

> -----Original Message-----
> From: Alexandre Oberlin [mailto:alxobr@xxxxxxxxx]
> Sent: Thursday, April 10, 2008 9:42 AM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Re: Very lazy deletion with Qt::WA_DeleteOnClose widget
> attribute set in Qt 4.2.2
> 
> Scott Aron Bloom écrivit:
> > This is CORRECT behavior....
> Sure. But it is annoying when your brand new widget gets deleted ;-)
> 
> --
> AO
> 
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/

--
 [ signature omitted ] 

Message 5 in thread

Scott Aron Bloom écrivait:
> The only way that would happen is if your new widget sets directly or via a parent path, 
> its parent pointer to the recently closed widget...
Yes, what gets deleted is a pointer to the subwidget in the parent window. 

> Which is a logic mistake on your part.... 
Why ?

> My question, if you have a widget that is being recreated... why mark it as being deleted on close
So that the destructor is always called, because it gets rid of many member objects that will have to be reconstructed. 
Concretely, this happens upon the closing of a file and the loading of a new file. The subwidget takes its data from the file.


Thanks for your interest.

-- 
 [ signature omitted ] 

Message 6 in thread

Alexandre Oberlin wrote:
> So that the destructor is always called, because it gets rid of many 
> member objects that will have to be reconstructed. Concretely, this 
> happens upon the closing of a file and the loading of a new file. The 
> subwidget takes its data from the file.
> 

You can try this approach:
martinfowler.com/apsupp/appfacades.pdf

Effectively, it allows one to separate GUI logic from the application logic.
No need than to destroy data model only if you need recreate a widget.

HTH,
Albert

--
 [ signature omitted ] 

Message 7 in thread

Albert Zhykhar écrivait:
> You can try this approach:
> martinfowler.com/apsupp/appfacades.pdf
> 
> Effectively, it allows one to separate GUI logic from the application 
> logic.
> No need than to destroy data model only if you need recreate a widget.

Thank you Albert, this looks interesting.
A bit of theory should not harm those days ;-)

-- 
 [ signature omitted ] 

Message 8 in thread

Scott Aron Bloom écrivit:
> The only way that would happen is if your new widget sets directly or
> via a parent path, its parent pointer to the recently closed
> widget...
I'm not sure what you mean. The situation is quite simple, the subwidget does not set its parent.
In the parent you have:
SubWidget * mysub;
mysub=new SubWidget(this, file1);
// have fun
mysub->close(); //  Qt::WA_DeleteOnClose is set, so I did not call the destructor explicitely
mysub=new SubWidget(this, file2);
// no fun, mysub is completely wrecked ;-)

-- 
 [ signature omitted ] 

Message 9 in thread

Please post some real code :)  Because I am interested in this issue...

However, looking a the code you posted, I don't see how mysub is wrecked...

That said, I don't know what SubWidget is...

Scott

> -----Original Message-----
> From: Alexandre Oberlin [mailto:alxobr@xxxxxxxxx]
> Sent: Thursday, April 10, 2008 12:28 PM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Re: Very lazy deletion with Qt::WA_DeleteOnClose widget
> attribute set in Qt 4.2.2
> 
> Scott Aron Bloom écrivit:
> > The only way that would happen is if your new widget sets directly or
> > via a parent path, its parent pointer to the recently closed
> > widget...
> I'm not sure what you mean. The situation is quite simple, the
> subwidget does not set its parent.
> In the parent you have:
> SubWidget * mysub;
> mysub=new SubWidget(this, file1);
> // have fun
> mysub->close(); //  Qt::WA_DeleteOnClose is set, so I did not call the
> destructor explicitely
> mysub=new SubWidget(this, file2);
> // no fun, mysub is completely wrecked ;-)
> 
> --
> AO
> 
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/

--
 [ signature omitted ] 

Message 10 in thread

Scott Aron Bloom écrivit:
> Please post some real code :)  Because I am interested in this issue...
> 
> However, looking a the code you posted, I don't see how mysub is wrecked...
> 
> That said, I don't know what SubWidget is...

Well, it is a big thing. But as I said calling delete solves the problem.
Here is some more pidgin code.
You'll have to talk to my boss for more ;-)

/////////////////////////////////////////////////////////////////////
class TopWidget : public QMainWindow
{
  // ...
  QAction *ac_load;
  SubWidget * mysub; 
  QMenu *mn_file;
  QToolBar *tb_file;
  // ...
}

TopWIdget::TopWidget()
{
  // ...
    mysub=NULL;
    ac_load = new QAction(QIcon( ":/fileopen.xpm" ), tr( "&Open..." ), this);
    ac_load->setObjectName("ac_load");
    ac_load->setShortcut(tr("Ctrl+O"));
    mn_file = new QMenu(tr( "&File" ), this );
    menuBar()->addMenu(mn_file );
    mn_file->addAction(ac_load); 
    tb_file = addToolBar(tr("Standard operations"));
    tb_file->addAction(ac_load);
    connect( ac_load, SIGNAL( triggered() ), this, SLOT( load() ) ); 
  // ...
}

void TopWidget::load()
{
  if (mysub != NULL)  unLoad();
  file1=askForFile();
  mysub=new SubWidget(this, file1); 
  // ...
}

void TopWidget::unLoad()
{
  if (mysub == NULL)  return;
  while (! mysub->close()) ;  
  //  delete mysub;  // UNCOMMENT AND EVERYTHING WORKS FINE
  mysub=NULL;
  // ...
}
/////////////////////////////////////////////////////////////////////

-- 
 [ signature omitted ] 

Message 11 in thread

The basic question is this...

What are the side-effects of calling a close of an object, which will eventually call deleteLater.  

But lets look at your unload
void TopWidget::unLoad()
{
  if (mysub == NULL)  return;
  while (! mysub->close()) ;  
  //  delete mysub;  // UNCOMMENT AND EVERYTHING WORKS FINE
  mysub=NULL;
  // ...
}

Why the loop on mysub->close() ?  

Here is my reason... the first time, your done... It will NOT happen until the event loop is called...

However, if you force an event loop, you run the risk of anyone who is pointed to it of crashing with expired pointer..  Which is pretty much what I said earlier...

Now, by deleting it, it CLOSES itself (normal behavior for all qwidgets)..

For your system... forget the "close" call, close is a best used as a slot from user events, or when you plan on re-opening it... I would just call delete..  

I thought there was a reason you called close, like events in the subwidget that occur on the close... but if the only reason you call close is to close the window and you need to delete it as well... 

Calling delete is event loop independent, setting mysub to NULL, next will guarantee that no one else uses it...


Note, I bet if you kept your code the same (called close() ) and use QPointer for mysub... it would work just fine


Scott



-----Original Message-----
From: Alexandre Oberlin [mailto:alxobr@xxxxxxxxx] 
Sent: Saturday, April 12, 2008 8:09 AM
To: qt-interest@xxxxxxxxxxxxx
Subject: Re: Very lazy deletion with Qt::WA_DeleteOnClose widget attribute set in Qt 4.2.2

Scott Aron Bloom écrivit:
> Please post some real code :)  Because I am interested in this issue...
> 
> However, looking a the code you posted, I don't see how mysub is wrecked...
> 
> That said, I don't know what SubWidget is...

Well, it is a big thing. But as I said calling delete solves the problem.
Here is some more pidgin code.
You'll have to talk to my boss for more ;-)

/////////////////////////////////////////////////////////////////////
class TopWidget : public QMainWindow
{
  // ...
  QAction *ac_load;
  SubWidget * mysub; 
  QMenu *mn_file;
  QToolBar *tb_file;
  // ...
}

TopWIdget::TopWidget()
{
  // ...
    mysub=NULL;
    ac_load = new QAction(QIcon( ":/fileopen.xpm" ), tr( "&Open..." ), this);
    ac_load->setObjectName("ac_load");
    ac_load->setShortcut(tr("Ctrl+O"));
    mn_file = new QMenu(tr( "&File" ), this );
    menuBar()->addMenu(mn_file );
    mn_file->addAction(ac_load); 
    tb_file = addToolBar(tr("Standard operations"));
    tb_file->addAction(ac_load);
    connect( ac_load, SIGNAL( triggered() ), this, SLOT( load() ) ); 
  // ...
}

void TopWidget::load()
{
  if (mysub != NULL)  unLoad();
  file1=askForFile();
  mysub=new SubWidget(this, file1); 
  // ...
}

void TopWidget::unLoad()
{
  if (mysub == NULL)  return;
  while (! mysub->close()) ;  
  //  delete mysub;  // UNCOMMENT AND EVERYTHING WORKS FINE
  mysub=NULL;
  // ...
}
/////////////////////////////////////////////////////////////////////

-- 
 [ signature omitted ]