Open shusaura85 opened 2 weeks ago
I believe this is due to a small mistake in the generateTerrainAroundCliffs
function. That function was implemented as part of #2383, which was merged for v24.04. This too will be fixed by #2615.
Still crashes in 24.09.1 if the ObjData files are not present. This bug doesn't appear to be fixed
Dump files give the same error:
FAILURE_BUCKET_ID: NULL_CLASS_PTR_READ_c0000005_openloco.dll!Unknown
ExceptionAddress: 6205cdcb (openloco+0x000acdcb)
ExceptionCode: c0000005 (Access violation)
1st crash - both objdata files missing.zip 2nd crash - 1 file missing (SHINKF0.DAT).zip
I can still repro this on c71cd567f104ef2dcb55cded95f9a36cd0b1e33a
Also looks like Snowy Heights can repro the terrain generation bug.
I think this is really two bugs: one with ObjData installation (that would only repro with custom scenario installation that installs objects, e.g. specifically "Shinkansen Land 1970"
And a second bug which appears to be a deterministic crash when deallocating the height map:
unmap_chunk(): invalid pointer
Thread 1 "OpenLoco" received signal SIGABRT, Aborted.
0xf7fc7579 in __kernel_vsyscall ()
(gdb) bt 20
#0 0xf7fc7579 in __kernel_vsyscall ()
#1 0xf731af97 in ?? () from /lib/i386-linux-gnu/libc.so.6
#2 0xf72c80b5 in raise () from /lib/i386-linux-gnu/libc.so.6
#3 0xf72af2bf in abort () from /lib/i386-linux-gnu/libc.so.6
#4 0xf72b037d in ?? () from /lib/i386-linux-gnu/libc.so.6
#5 0xf73268dd in ?? () from /lib/i386-linux-gnu/libc.so.6
#6 0xf7326bdb in ?? () from /lib/i386-linux-gnu/libc.so.6
#7 0xf732b2b5 in free () from /lib/i386-linux-gnu/libc.so.6
#8 0xf759715c in operator delete(void*) () from /lib/i386-linux-gnu/libstdc++.so.6
#9 0xf759718c in operator delete(void*, unsigned int) () from /lib/i386-linux-gnu/libstdc++.so.6
#10 0x0117981d in std::__new_allocator<unsigned char>::deallocate (this=0xffffc8dc,
__p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037 \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\032\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., __n=147456) at /usr/include/c++/13/bits/new_allocator.h:172
#11 0x011719ea in std::allocator<unsigned char>::deallocate (__n=147456,
__p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037 \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\032\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., this=0xffffc8dc) at /usr/include/c++/13/bits/allocator.h:210
#12 std::allocator_traits<std::allocator<unsigned char> >::deallocate (__n=147456,
__p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037 \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\032\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., __a=...) at /usr/include/c++/13/bits/alloc_traits.h:517
#13 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_deallocate (this=0xffffc8dc,
__p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037 \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\0--Type <RET> for more, q to quit, c to continue without paging--
32\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., __n=147456) at /usr/include/c++/13/bits/stl_vector.h:390
#14 0x0116d495 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::~_Vector_base (this=0xffffc8dc,
__in_chrg=<optimized out>) at /usr/include/c++/13/bits/stl_vector.h:369
#15 0x0116c97f in std::vector<unsigned char, std::allocator<unsigned char> >::~vector (this=0xffffc8dc,
__in_chrg=<optimized out>) at /usr/include/c++/13/bits/stl_vector.h:738
#16 0x01278ba0 in OpenLoco::World::MapGenerator::HeightMap::~HeightMap (this=0xffffc8dc, __in_chrg=<optimized out>)
at /openloco/src/OpenLoco/src/Map/MapGenerator/HeightMap.h:11
#17 0x01277d1b in OpenLoco::World::MapGenerator::generate (options=...)
at /openloco/src/OpenLoco/src/Map/MapGenerator/MapGenerator.cpp:1046
#18 0x0130ef64 in OpenLoco::Scenario::generateLandscape () at /openloco/src/OpenLoco/src/Scenario.cpp:252
#19 0x0130f72f in OpenLoco::Scenario::start () at /openloco/src/OpenLoco/src/Scenario.cpp:362
Exact crash isn't perfectly deterministic - sometimes I get this message:
free(): invalid size which implies a good old fashioned memory corruption most likely Unfortunately, I can't get it to run under valgrind, I'm sure I'm doing something stupid.
valgrind ./OpenLoco
==9114== Memcheck, a memory error detector
==9114== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==9114== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==9114== Command: ./OpenLoco
==9114==
OpenLoco, v24.09.1-1 (c71cd567 on master, DEBUG)
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 4 (X_DestroyWindow)
Resource id in failed request: 0x2e00002
Serial number of failed request: 139
Current serial number in output stream: 139
==9114==
==9114== HEAP SUMMARY:
==9114== in use at exit: 580,429 bytes in 2,516 blocks
==9114== total heap usage: 22,302 allocs, 19,786 frees, 2,855,546 bytes allocated
==9114==
==9114== LEAK SUMMARY:
==9114== definitely lost: 0 bytes in 0 blocks
==9114== indirectly lost: 0 bytes in 0 blocks
==9114== possibly lost: 0 bytes in 0 blocks
==9114== still reachable: 580,429 bytes in 2,516 blocks
==9114== suppressed: 0 bytes in 0 blocks
==9114== Rerun with --leak-check=full to see details of leaked memory
==9114==
==9114== For lists of detected and suppressed errors, rerun with: -s
==9114== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
@AaronVanGeffen this is a progress bar issue. When installing an object it unloads all objects the progress bar then tries to render but with objects unloaded it crashes.
I don't think so?
I tried commenting out the relevant progress updates
{
HeightMap heightMap(kMapColumns, kMapRows);
generateHeightMap(options, heightMap);
//updateProgress(25);
generateRivers(options, heightMap);
//updateProgress(30);
generateLand(heightMap);
//updateProgress(35);
generateWater(heightMap);
//updateProgress(45);
generateTerrain(heightMap);
//updateProgress(55);
}
generateSurfaceVariation();
//updateProgress(175);
And recompiled of course.
It seems to be a double free or other memory corruption (and the error messages agree):
double free or corruption (out)
at line 1046
When HeightMap heightMap(kMapColumns, kMapRows); leaves scope and thus is destroyed. What I can't work out, is what's going wrong...
{
HeightMap heightMap(kMapColumns, kMapRows);
//generateHeightMap(options, heightMap);
//updateProgress(25);
//generateRivers(options, heightMap);
//updateProgress(30);
//generateLand(heightMap);
//updateProgress(35);
//generateWater(heightMap);
//updateProgress(45);
//generateTerrain(heightMap);
//updateProgress(55);
}
This works "fine" as long as one wants to live on a perfectly flat world. The minute one uncomments generateHeightMap, things go boom.
So my theory (haven't found the exact point yet) is that somewhere along the line, the pointer to heightMap::_height is freed. Possibly by existing assembly code? or by C++ code I haven't found yet.
Which results in a 100% deterministic double free crash when heightMap leaves scope.
Yeah, definitely looks to be the case
{
// Intentional leak... someone else is freeing the heightMap._height
HeightMap* heightMap = new HeightMap(kMapColumns, kMapRows);
generateHeightMap(options, *heightMap);
updateProgress(25);
generateRivers(options, *heightMap);
updateProgress(30);
generateLand(*heightMap);
updateProgress(35);
generateWater(*heightMap);
updateProgress(45);
generateTerrain(*heightMap);
updateProgress(55);
}
Also works fine and actually generates terrain! (but leaks the wrapper struct, but not the big array probably)
Theory somewhat busted:
HeightMap* heightMap = new HeightMap(kMapColumns, kMapRows);
generateHeightMap(options, *heightMap);
generateHeightMap(options, *heightMap);
Would crash if that pointer was being freed But I'm pretty confused.
Given that I have a workaround (leak the heightmap), I think that's enough debugging for me for one day... hope the data helps.
Oh... ok, so that's even more fun. If I try to leak it, it generates fine. But quitting to the menu now deterministically crashes instead. What cursed (arena based?) memory management shenanigans am I overlooking here?
free(): invalid next size (normal)
Thread 1 "OpenLoco" received signal SIGABRT, Aborted.
0xf7fc7579 in __kernel_vsyscall ()
(gdb) bt 20
#0 0xf7fc7579 in __kernel_vsyscall ()
#1 0xf731af97 in __pthread_kill_implementation (threadid=threadid@entry=4137756608, signo=signo@entry=6,
no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:43
#2 0xf731b01f in __pthread_kill_internal (signo=6, threadid=4137756608) at ./nptl/pthread_kill.c:78
#3 0xf72c80b5 in __GI_raise (sig=6) at ../sysdeps/posix/raise.c:26
#4 0xf72af2bf in __GI_abort () at ./stdlib/abort.c:79
#5 0xf72b037d in __libc_message_impl (fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:132
#6 0xf73268dd in malloc_printerr (str=str@entry=0xf7456cf8 "free(): invalid next size (normal)")
at ./malloc/malloc.c:5772
#7 0xf73288bb in _int_free_merge_chunk (av=av@entry=0xf74bd760 <main_arena>, p=p@entry=0x432c1b8,
size=size@entry=129488) at ./malloc/malloc.c:4684
#8 0xf7328c20 in _int_free (av=av@entry=0xf74bd760 <main_arena>, p=0x432c1b8, have_lock=<optimized out>,
have_lock@entry=0) at ./malloc/malloc.c:4646
#9 0xf732b267 in __GI___libc_free (mem=0x432c1c0) at ./malloc/malloc.c:3398
#10 0x012c83f7 in OpenLoco::ObjectManager::unload (header=...)
at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:567
#11 0x012c9527 in operator() (__closure=0xffffc8eb, handle=...)
at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#12 0x012ca168 in OpenLoco::ObjectManager::forEachLoadedObject<OpenLoco::ObjectManager::unloadAll()::<lambda(const OpenLoco::LoadedObjectHandle&)> >(struct {...} &&) (func=...) at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.h:210
#13 0x012c9554 in OpenLoco::ObjectManager::unloadAll () at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#14 0x013151a0 in OpenLoco::Title::start () at /OpenLoco/src/OpenLoco/src/Title.cpp:154
#15 0x011ce2f5 in OpenLoco::Game::returnToTitle () at /OpenLoco/src/OpenLoco/src/Game.cpp:263
#16 0x011e00b5 in OpenLoco::GameCommands::loadSaveQuit (args=..., flags=1 '\001')
at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:64
#17 0x011e0112 in OpenLoco::GameCommands::loadSaveQuit (regs=...)
at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:77
#18 0x011deb4d in OpenLoco::GameCommands::callGameCommandFunction (command=21, regs=...)
at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:354
#19 0x011ded5f in OpenLoco::GameCommands::loc_4313C6 (esi=21, regs=...)
at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:416
(More stack frames follow...)
(gdb) bt 40
#0 0xf7fc7579 in __kernel_vsyscall ()
#1 0xf731af97 in __pthread_kill_implementation (threadid=threadid@entry=4137756608, signo=signo@entry=6,
no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:43
#2 0xf731b01f in __pthread_kill_internal (signo=6, threadid=4137756608) at ./nptl/pthread_kill.c:78
#3 0xf72c80b5 in __GI_raise (sig=6) at ../sysdeps/posix/raise.c:26
#4 0xf72af2bf in __GI_abort () at ./stdlib/abort.c:79
#5 0xf72b037d in __libc_message_impl (fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:132
#6 0xf73268dd in malloc_printerr (str=str@entry=0xf7456cf8 "free(): invalid next size (normal)")
at ./malloc/malloc.c:5772
#7 0xf73288bb in _int_free_merge_chunk (av=av@entry=0xf74bd760 <main_arena>, p=p@entry=0x432c1b8,
size=size@entry=129488) at ./malloc/malloc.c:4684
#8 0xf7328c20 in _int_free (av=av@entry=0xf74bd760 <main_arena>, p=0x432c1b8, have_lock=<optimized out>,
have_lock@entry=0) at ./malloc/malloc.c:4646
#9 0xf732b267 in __GI___libc_free (mem=0x432c1c0) at ./malloc/malloc.c:3398
#10 0x012c83f7 in OpenLoco::ObjectManager::unload (header=...)
at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:567
#11 0x012c9527 in operator() (__closure=0xffffc8eb, handle=...)
at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#12 0x012ca168 in OpenLoco::ObjectManager::forEachLoadedObject<OpenLoco::ObjectManager::unloadAll()::<lambda(const OpenLoco::LoadedObjectHandle&)> >(struct {...} &&) (func=...) at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.h:210
#13 0x012c9554 in OpenLoco::ObjectManager::unloadAll () at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#14 0x013151a0 in OpenLoco::Title::start () at /OpenLoco/src/OpenLoco/src/Title.cpp:154
#15 0x011ce2f5 in OpenLoco::Game::returnToTitle () at /OpenLoco/src/OpenLoco/src/Game.cpp:263
#16 0x011e00b5 in OpenLoco::GameCommands::loadSaveQuit (args=..., flags=1 '\001')
at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:64
#17 0x011e0112 in OpenLoco::GameCommands::loadSaveQuit (regs=...)
at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:77
#18 0x011deb4d in OpenLoco::GameCommands::callGameCommandFunction (command=21, regs=...)
at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:354
#19 0x011ded5f in OpenLoco::GameCommands::loc_4313C6 (esi=21, regs=...)
at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:416
#20 0x011deaf7 in OpenLoco::GameCommands::doCommandForReal (
command=OpenLoco::GameCommands::GameCommand::loadSaveQuitGame, company=0, regs=...)
at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:346
#21 0x011de95f in OpenLoco::GameCommands::doCommand (command=OpenLoco::GameCommands::GameCommand::loadSaveQuitGame,
regs=...) at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:306
#22 0x011cf8e4 in OpenLoco::GameCommands::doCommand<OpenLoco::GameCommands::LoadSaveQuitGameArgs> (args=...,
flags=1 '\001') at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.h:138
#23 0x014188e9 in OpenLoco::Ui::Windows::ToolbarTop::Game::loadsaveMenuDropdown (
window=0x1a1b0f4 <OpenLoco::Ui::WindowManager::_windows+5428>, widgetIndex=0 '\000', itemIndex=8)
at /OpenLoco/src/OpenLoco/src/Windows/ToolbarTop.cpp:261
#24 0x01419c84 in OpenLoco::Ui::Windows::ToolbarTop::Game::onDropdown (window=..., widgetIndex=0 '\000', itemIndex=8)
at /OpenLoco/src/OpenLoco/src/Windows/ToolbarTop.cpp:714
#25 0x0133dd1b in OpenLoco::Ui::Window::callOnDropdown (this=0x1a1b0f4 <OpenLoco::Ui::WindowManager::_windows+5428>,
widgetIndex=0 '\000', itemIndex=8) at /OpenLoco/src/OpenLoco/src/Ui/Window.cpp:1101
#26 0x0123f942 in OpenLoco::Input::dropdownRegisterSelection (item=8)
at /OpenLoco/src/OpenLoco/src/Input/MouseInput.cpp:894
#27 0x0124018f in OpenLoco::Input::stateWidgetPressed (button=OpenLoco::Input::MouseButton::leftReleased, x=63,
y=115, window=0x1a1d0c2 <OpenLoco::Ui::WindowManager::_windows+13570>,
widget=0x1a1d950 <OpenLoco::Ui::WindowManager::_windows+15760>, widgetIndex=0 '\000')
at /OpenLoco/src/OpenLoco/src/Input/MouseInput.cpp:1076
#28 0x0123e120 in OpenLoco::Input::handleMouse (x=63, y=115, button=OpenLoco::Input::MouseButton::leftReleased)
at /OpenLoco/src/OpenLoco/src/Input/MouseInput.cpp:380
#29 0x0131b3e6 in OpenLoco::Ui::handleInput () at /OpenLoco/src/OpenLoco/src/Ui.cpp:899
#30 0x012d6d1c in OpenLoco::sub_431695 (var_F253A0=1) at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:302
#31 0x012d71dd in OpenLoco::tick () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:448
#32 0x012d819c in OpenLoco::variableUpdate () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:731
#33 0x012d836f in OpenLoco::update () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:771
#34 0x012d83ab in OpenLoco::run () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:786
#35 0x012d8811 in OpenLoco::main (options=...) at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:881
#36 0x012d8b8f in OpenLoco::main (argv=...) at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:902
#37 0x01270601 in main (argc=1, argv=0xffffd144) at /OpenLoco/src/OpenLoco/src/Main.cpp:28
Duncan is talking about a different set of progress bars. The object loading happens during the S5 import routines, not the map generation.
Oh - I see. He's talking about the scenario loading bug Whereas I was talking about the other bug that also impacts Shinkansen Land - the landscape generation one. Would it help if I opened a separate issue to track that?
Shinkansen Land 1970 generates fine for me, provided the objects are present. I can reproduce a crash on Snowy Heights, though. As randomness is involved, luck can sway either way, though. I'll look into it.
Shinkansen Land 1970 generates fine for me, provided the objects are present. I can reproduce a crash on Snowy Heights, though. As randomness is involved, luck can sway either way, though. I'll look into it.
This issue was supposed to be about the crash when saving the objects inside the scenario. Looks like it got hijacked for terrain generation bugs
This issue was supposed to be about the crash when saving the objects inside the scenario. Looks like it got hijacked for terrain generation bugs
Don't worry, we have not forgotten the issue with object extraction.
Version information:
Describe the bug Game crashes when starting the Shinkansen scenario.
In 24.09, it crashes every time (caused by random landscape generation bug).
In 24.05 to 24.08, it crashes if the ObjData files SHINKT0.DAT and SHINKF0.DAT are missing and need to be installed by the scenario.
In this case, it crashes after saving the first object,
then it crashes after saving the second object,
3rd attempt will load the scenario successfully.
To Reproduce
Expected behaviour Doesn't crash
Additional context In 24.09 it crashes when "Generating landscape..."
Attached dump from 24.08 as 24.09 has another bug with random landscape generation
b372fe7c-36ad-44b4-a847-713c222a27af(OpenLoco, v24.08 (40e9b7bf on master)).zip