call bug in the constructor. See docs/wrong_virtual_call.md for a description.
1.3 KiB
-
SizeNotifiable, defined as the following:
class SizeNotifiable<RegisterBehaviour, true> : private RegisterBehaviour, public SizeNotifiableBase { ... };
gets constructed - it inherits from SizeNotifiableBase which declares NotifyResChanged() as virtual. It also inherits from RegisterBehaviour, which must provide a Register() method.
-
In SizeNotifiable's constructor RegisterBehaviour::Register(this) gets called. Being in the constructor, virtual calls on this are UB.
-
When RegisterBehaviour == AutoRegister, we have Register defined as the following:
void AutoRegister::Register (SizeNotifiableBase* parNotifiable) { m_id = m_sdlmain->RegisterForResChange(parNotifiable); }
note that parNotifiable is received from SizeNotifiable's constructor, so it's a partially constructed object.
-
RegisterForResChange() is defined as:
size_t SDLMain::RegisterForResChange (SizeNotifiableBase* parNotif) { parNotif->NotifyResChanged(m_localData->sizeratio); return m_localData->resChangeNotifList.Add(parNotif); }
parNotif is, again, the partly constructed object pointed by this in SizeNotifiable's constructor. NotifyResChanged() is a virtual method, thus the bug. Objects being registered need to be notified straight away since they have no clue about the current size held by SDLMain.