[Buttons & Timers] Деструктора на Wheel се извиква след като е освободен gTimerMgr
Привет, колеги!
Докато правих заданието към "Buttons & Timers" (в общи линии съм следвал това, което сме правили на лекцията) забелязах, че при излизане от програмата AddressSanitizer-a хвърля следната грешка:
AddressSanitizer:DEADLYSIGNAL:
hashtable.h
SEGV on unknown address 0x000000000058 (pc 0x560f914507f4 bp 0x7ffd48a7e0a0 sp 0x7ffd48a7e080 T0)
...
std::unordered_set<int, std::hash, std::equal_to, std::allocator>::find(int const&) const
TimerManager::isActiveTimerId(int) const
TimerClient::isActiveTimerId(int) const
Wheel::~Wheel()
Game::~Game()
Engine::~Engine()
runApplication
main
__libc_start_main
_start
Проблемът е, че деструктора на Wheel:
Wheel::~Wheel() {
if (isActiveTimerId(_rotateAnimationTimerId)) {
stopTimer(_rotateAnimationTimerId);
}
}
се извиква след рилийза на gTimerMgr и съответно при извикването на TimerClient::isActiveTimerId() той е nullptr.
Заобиколих го като добавих проверка за gTimerMgr:
bool TimerClient::isActiveTimerId(const int32_t timerId) const {
return gTimerMgr && gTimerMgr->isActiveTimerId(timerId);
}
Някой друг натъквал ли се е на проблеми от подобно естество с проекта?
Привет, Мартин,
Или не съм се изразил правилно, или не си ме разбрал.
По време на лекцията предложих алтернативен вариант, в който не зависим от подредбата на елементите.
Разбира се, този подход има малка лимитация, че не трябва да използваме обекти като Hero и Whеel извън нашия Engine.
Смятам, че не е края на света, ако имаме тази лимитация.
Все пак тези обекти биха пренадлежали на Game, а не на Engine.
Моето предложение:
Товага ще създадем и унищоваме ManagerHandler външно за Engine-а като гарантираме, че той (и респективно глобалните Singletons) ще са живи, докато имаме Engine (и по време не целия му destruction call stack).
Поздрави
Привет, Живко,
Благодаря за уточнението и най-вече за кода, защото има много тънък момент в него! :)
Опитах това, което предлагаш и наистина работи, като разковничето е в това, че ръчно менажираме живота на Engine обекта и го "убиваме" преди да се излезе от runApplication() (с engine.reset() или delete engine, ако използваме raw pointer) - без този ред проблемът си остава.
Поздрави!