Featured image of post Side Quest - Beware of side effects!

Side Quest - Beware of side effects!

A small programming faux pas tale to keep your mind alert.

Side Quest - Beware of side effects!

This is the first in a series of mini programming blog posts I’ve titled ‘Side Quest’. I plan to make more of these in the future too!

I have recently been working on a new GUI for the Xenia Emulator. Yesterday I encountered a strange issue with the code for the Combobox widget… In “Debug” builds everything worked fine. But in “Release” builds, the combobox was empty! The bulk of the code is shown below, see if you can spot the issue.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SettingsComboBox::SettingsComboBox(IMultiChoiceSettingsItem& item)
    : XComboBox(), item_(item) {
  assert_true(Initialize(), "Could not initialize SettingsComboBox");
}

bool SettingsComboBox::Initialize() {
  setMaximumWidth(kComboboxMaxWidth);

  // load combobox items from setting
  for (const std::string& option : item_.option_names()) {
    addItem(option.c_str());
  }

  // set default value to match cvar
  int index = static_cast<int>(item_.current_index());
  setCurrentIndex(index);

  // update selected multi-choice item when index changes
  connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged),
          [&item = item_](int index) { item.set_selection(index); });

  return true;
}

If you spotted the mistake quickly, it is very likely you have encountered this problem previously, as it’s one they don’t teach you in programming school.

The problem was that in “Release” mode, the assert_true() macro is compiled out so Initialize() is never called! This bug took me way too long to spot, made harder by the lack of errors.

The lesson here is of course: don’t execute code with side-effects in an assert block

Built with Hugo
Theme Stack designed by Jimmy