Debian GNU/Linux 11 (bullseye)
OXCE 7.5.13 (140cb067)
XPiratez M5.2.1
Crash when finishing research on Humanist Activist, see attached savegame.
Debugging attempt below, using gdb on debug build:
Program received signal SIGSEGV, Segmentation fault.
0x0000555556094258 in __gnu_cxx::__normal_iterator<OpenXcom::RuleResearch const* const*, std::vector<OpenXcom::RuleResearch const*, std::allocator<OpenXcom::RuleResearch const*> > >::__normal_iterator (this=0x7fffffffcd08, __i=@0x5555000002d0: <error reading variable>)
at /usr/include/c++/10/bits/stl_iterator.h:979
979 : _M_current(__i) { }
Checking the stack
(gdb) bt
#0 0x0000555556094258 in __gnu_cxx::__normal_iterator<OpenXcom::RuleResearch const* const*, std::vector<OpenXcom::RuleResearch const*, std::allocator<OpenXcom::RuleResearch const*> > >::__normal_iterator (this=0x7fffffffcd08, __i=@0x5555000002d0: <error reading variable>)
at /usr/include/c++/10/bits/stl_iterator.h:979
#1 0x0000555556094169 in std::vector<OpenXcom::RuleResearch const*, std::allocator<OpenXcom::RuleResearch const*> >::end (this=0x5555000002c8) at /usr/include/c++/10/bits/stl_vector.h:839
#2 0x0000555556093f7a in std::vector<OpenXcom::RuleResearch const*, std::allocator<OpenXcom::RuleResearch const*> >::empty (this=0x5555000002c8) at /usr/include/c++/10/bits/stl_vector.h:1008
#3 0x00005555569dfe5f in OpenXcom::SavedGame::selectGetOneFree (this=0x55555ba856d0, research=0x555500000100) at ../src/Savegame/SavedGame.cpp:1525
#4 0x000055555643e8c6 in OpenXcom::GeoscapeState::time1Day (this=0x55555d22a8d0) at ../src/Geoscape/GeoscapeState.cpp:2383
#5 0x0000555556434cce in OpenXcom::GeoscapeState::timeAdvance (this=0x55555d22a8d0) at ../src/Geoscape/GeoscapeState.cpp:876
#6 0x00005555563e1fc2 in OpenXcom::Timer::think (this=0x7fffc6057dc0, state=0x55555d22a8d0, surface=0x0) at ../src/Engine/Timer.cpp:123
#7 0x000055555643430b in OpenXcom::GeoscapeState::think (this=0x55555d22a8d0) at ../src/Geoscape/GeoscapeState.cpp:753
#8 0x00005555562d33a9 in OpenXcom::Game::run (this=0x55555af41b30) at ../src/Engine/Game.cpp:334
#9 0x0000555556019f6b in main (argc=1, argv=0x7fffffffda98) at ../src/main.cpp:125
Through a bit of sleuthing I figure out the problem is in GeoscapeState::time1Day()
#4 0x000055555643e8c6 in OpenXcom::GeoscapeState::time1Day (this=0x55555d22a8d0) at ../src/Geoscape/GeoscapeState.cpp:2383
2383 if ((bonus = saveGame->selectGetOneFree(research)))
(gdb) list
2378 base->getStorageItems()->addItem(ruleCorpse->getType());
2379 }
2380 }
2381 }
2382 // 3c. handle getonefrees (topic+lookup)
2383 if ((bonus = saveGame->selectGetOneFree(research)))
2384 {
2385 saveGame->addFinishedResearch(bonus, mod, base);
2386 if (!bonus->getLookup().empty())
2387 {
Some relevant variables:
(gdb) print research
$1 = (const OpenXcom::RuleResearch *) 0x555500000100
Looks corrupted.
(gdb) print base
$2 = (OpenXcom::Base *) 0x55555ba4e5b0
(gdb) print project
$3 = (OpenXcom::ResearchProject *) 0x0
Somehow
project is NULL. Let's inspect how
finished is constructed, starting with
base->getResearch() (gdb) print base._research._M_impl._M_start
$6 = (std::_Vector_base<OpenXcom::ResearchProject*, std::allocator<OpenXcom::ResearchProject*> >::pointer) 0x55555bb25470
(gdb) print base._research.size()
$7 = 3
It is of size three.
(gdb) print base._research._M_impl._M_start[0]
$8 = (OpenXcom::ResearchProject *) 0x55555bbae600
(gdb) print base._research._M_impl._M_start[1]
$9 = (OpenXcom::ResearchProject *) 0x55555bbae410
(gdb) print base._research._M_impl._M_start[2]
$10 = (OpenXcom::ResearchProject *) 0x55555bbaea00
No NULL here.
(gdb) print finished
$11 = {<std::_Vector_base<OpenXcom::ResearchProject*, std::allocator<OpenXcom::ResearchProject*> >> = {
_M_impl = {<std::allocator<OpenXcom::ResearchProject*>> = {<__gnu_cxx::new_allocator<OpenXcom::ResearchProject*>> = {<No data fields>}, <No data fields>}, <std::_Vector_base<OpenXcom::ResearchProject*, std::allocator<OpenXcom::ResearchProject*> >::_Vector_impl_data> = {
_M_start = 0x7fffb951cdf0, _M_finish = 0x7fffb951ce10, _M_end_of_storage = 0x7fffb951ce10}, <No data fields>}}, <No data fields>}
(gdb) print finished.size()
$12 = 4
Aha! An extra project seems to have been added somehow. Let's look closer.
(gdb) print finished._M_impl._M_start
$13 = (std::_Vector_base<OpenXcom::ResearchProject*, std::allocator<OpenXcom::ResearchProject*> >::pointer) 0x7fffb951cdf0
(gdb) print finished._M_impl._M_start[0]
$14 = (OpenXcom::ResearchProject *) 0x55555bbaf3e0
(gdb) print finished._M_impl._M_start[1]
$15 = (OpenXcom::ResearchProject *) 0x55555bbae000
(gdb) print finished._M_impl._M_start[2]
$16 = (OpenXcom::ResearchProject *) 0x55555bbaedc0
(gdb) print finished._M_impl._M_start[3]
$17 = (OpenXcom::ResearchProject *) 0x55555bbaea00
Here I manage to hang gdb by attempting to print
finished._M_impl._M_start[0]._project._name.
Let's start over and just print
finished._M_impl._M_start[0]._project instead. I also added some debug prints.
Still crashes in OpenXcom::GeoscapeState::time1Day.
added 0x55555bb39440
added 0x55555bb380b0
added 0x55555bb38a40
added 0x55555bb38850
saveGame->getAvailableResearchProjects
processing 0x55555bb39440 0x7fffb34e2640
processing 0x55555bb380b0 0x7fffb346ce90
processing 0x55555bb38a40 0x555500000100
*crash*
It seems four projects were added to
finished after all. And yet
base._research.size() == 3.
The last three are fprintf(stderr, "processing %p %p\n", project, research);
In calling OpenXcom::SavedGame::selectGetOneFree()
project (but not
research) gets set to NULL:
(gdb) print project
$1 = (OpenXcom::ResearchProject *) 0x0
(gdb) print research
$2 = (const OpenXcom::RuleResearch *) 0x555500000100
Through a process of elimination I've figured out this is "Humanist Activist" (STR_NAZI_KKK). What I don't understand is how that broken pointer gets in there.
For fun I try commenting out the call to getAvailableResearchProjects(), but that didn't help. I also confirmed
finished[2] is intact and only the copy of it in
project is borked.