Hey all,

Recently I catched a bug (or misdesign) in WMenu and
concluded for myself that slots should never perform
deletion of the objects which methods emit the related
signals. This may leads to undefined behavior.

Consider:

// WARNING: bad code!
//
// Gdb run command: run --docroot . --http-address 0.0.0.0 --http-port 8888
#include <Wt/WApplication>
#include <Wt/WMenu>
#include <Wt/WPopupMenu>
#include <Wt/WStackedWidget>

namespace {

class App : public Wt::WApplication {
public:
  App(const Wt::WEnvironment& env);
private:
  void del();

  Wt::WMenu* m_;
};

void App::del()
{
  // This slot will be called from WMenu::select():
  // ...
  // item->triggered().emit(item);
  // itemSelected_.emit(item);
  // ...
  // and thus leads to undefined behaviour, since `this'
  // will point to the deleted WMenu after item->triggered().emit(item).
  delete m_;
  m_ = 0;
}

App::App(const Wt::WEnvironment& env)
  : WApplication(env)
{
  using Wt::WText;

  Wt::WStackedWidget* const c = new Wt::WStackedWidget;
  root()->addWidget(c);

  // Menu
  m_ = new Wt::WMenu(c);
  root()->addWidget(m_);

  // Submenu
  Wt::WPopupMenu* const pm = new Wt::WPopupMenu(c);
  m_->addMenu("User Foo", pm);
  pm->addItem("Logout", this, &App::del);
}

Wt::WApplication* createApp(const Wt::WEnvironment& env)
{
  return new App(env);
}

} // namespace

int main(int argc, char* argv[])
{
  return Wt::WRun(argc, argv, createApp);
}

While the example above demonstrates a bug (or invalid usage
due to the lack of documentary cautions from such use) in WMenu,
IMO it demonstrates unrecommened and dangerous pratice in general.
Thus, I think that the rule: "slots should never perform deletion of the
objects which methods emit the related signals" should be documented
to prevent users from corresponding gotchas.

Thoughts?

-- 
// Dmitriy.
// WARNING: bad code!
//
// Gdb run command: run --docroot . --http-address 0.0.0.0 --http-port 8888
#include <Wt/WApplication>
#include <Wt/WMenu>
#include <Wt/WPopupMenu>
#include <Wt/WStackedWidget>

namespace {

class App : public Wt::WApplication {
public:
  App(const Wt::WEnvironment& env);
private:
  void del();

  Wt::WMenu* m_;
};

void App::del()
{ 
  // This slot will be called from WMenu::select():
  // ... 
  // item->triggered().emit(item);
  // itemSelected_.emit(item);
  // ...
  // and thus leads to undefined behaviour, since `this'
  // will point to the deleted WMenu after item->triggered().emit(item).
  delete m_;
  m_ = 0;
}

App::App(const Wt::WEnvironment& env)
  : WApplication(env)
{
  using Wt::WText;

  Wt::WStackedWidget* const c = new Wt::WStackedWidget;
  root()->addWidget(c);

  // Menu
  m_ = new Wt::WMenu(c);
  root()->addWidget(m_);

  // Submenu
  Wt::WPopupMenu* const pm = new Wt::WPopupMenu(c);
  m_->addMenu("User Foo", pm);
  pm->addItem("Logout", this, &App::del);
}

Wt::WApplication* createApp(const Wt::WEnvironment& env)
{
  return new App(env);
}

} // namespace

int main(int argc, char* argv[])
{
  return Wt::WRun(argc, argv, createApp);
}
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
witty-interest mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to