CleverRaven / Cataclysm-DDA

Cataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.
http://cataclysmdda.org
Other
10.61k stars 4.17k forks source link

Crash unloading bike rack #28712

Closed drayath closed 5 years ago

drayath commented 5 years ago

Describe the bug Crash when unloading a bike rack. Rack is a single rack on the back of a bike with a 1 tile cart loaded(frame, trunk, uni-wheel).

Unloading has worked in the past. Known changes since last worked: attached cart was damaged and repaired while attached, including unicycle wheel damaged to grey and repaired.

This is fully reproducible with attached game save (standing next to bike with issue): save.zip

CDDA Version: cataclysmdda-0.D-8588 (Windows 10-Tiles) Mods: "dda", "no_npc_food", "filthy_morale", "novitamins", "safeautodoc", "no_survivor_armor", "alt_map_key", "mutant_npcs", "more_locations", "FujiStruct", "oa_additional_buildings_mod", "Urban_Development", "generic_guns", "modular_turrets", "More_Survival_Tools", "Medieval_Stuff", "makeshift", "growable-pots"

Core Dump: core.zip CRASH LOG FILE: config/crash.log VERSION: 0.D-148-gdcfa1db TYPE: Signal MESSAGE: SIGSEGV: Segmentation fault STACK TRACE: @0x54C804[cataclysm-tiles.exe+0x14C804] @0x54CBA5[cataclysm-tiles.exe+0x14CBA5] SMPEG_error+0x3DAF3@0xBA2655[cataclysm-tiles.exe+0x7A2655] UnhandledExceptionFilter+0x1A0@0x77815F10[KERNELBASE.dll+0x195F10] RtlCaptureStackContext+0x1E521@0x77BBDA71[ntdll.dll+0x9DA71] RtlAreBitsSet+0x58@0x77B84198[ntdll.dll+0x64198]

ghost commented 5 years ago

image I believe this may be the same issue. I had a two tile motorbike in this situation.

I had altered both the motorbike (while attached), and the car (removed the heavy board) before attempting to unload.

I was able to work-around by disassembling the attached vehicle and recreating it as a new vehicle. After that it could load and unload without crash.

neitsa commented 5 years ago

Started investigating this crash.

Here's a full stack trace (error in frame 4):

0:000> kb
 # RetAddr           : Args to Child                                                           : Call Site
00 (Inline Function) : --------`--------  : Cataclysm!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Check_offset [d:\programming\microsoft visual studio 14.0\vc\include\xstring @ 2271] 
01 00007ff6`0b1ff8c8 : 00000013`f2cfd840  : Cataclysm!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::assign+0x15 [d:\programming\microsoft visual studio 14.0\vc\include\xstring @ 1150] 
02 (Inline Function) : --------`--------  : Cataclysm!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::{ctor}+0x20 [d:\programming\microsoft visual studio 14.0\vc\include\xstring @ 817] 
03 00007ff6`0bb5d959 : 00000000`00000000  : Cataclysm!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::substr+0x28 [d:\programming\microsoft visual studio 14.0\vc\include\xstring @ 2089] 
04 00007ff6`0bb8a68c : 0000018d`35a0f2e0  : Cataclysm!vehicle::remove_carried_vehicle+0x569 [cataclysm-dda\src\vehicle.cpp @ 1676] 
05 00007ff6`0bb82cdf : 00000013`f2cfdb00  : Cataclysm!vehicle::use_bike_rack+0x6cc [cataclysm-dda\src\vehicle_use.cpp @ 1347] 
06 00007ff6`0b9a9002 : 00000000`00000009  : Cataclysm!vehicle::interact_with+0xecf [cataclysm-dda\src\vehicle_use.cpp @ 1482] 
07 00007ff6`0b477491 : 00000000`00000009  : Cataclysm!Pickup::pick_up+0xc2 [cataclysm-dda\src\pickup.cpp @ 365] 
08 00007ff6`0b477ae9 : 0000018d`25a3c010  : Cataclysm!game::examine+0x181 [cataclysm-dda\src\game.cpp @ 5962] 
09 00007ff6`0b4cd5a6 : 0000018d`384d1600  : Cataclysm!game::examine+0x199 [cataclysm-dda\src\game.cpp @ 5879] 
0a 00007ff6`0b46fbb4 : 0000018d`267bb3d0  : Cataclysm!game::handle_action+0xfc6 [cataclysm-dda\src\handle_action.cpp @ 1471] 
0b 00007ff6`0b1f3f3c : 00000013`f2cfef00  : Cataclysm!game::do_turn+0x714 [cataclysm-dda\src\game.cpp @ 1402] 
0c 00007ff6`0b161232 : 0000018d`1d170018  : Cataclysm!SDL_main+0x117c [cataclysm-dda\src\main.cpp @ 682] 
0d 00007ff6`0bbe9663 : 00000000`00000000  : Cataclysm!main_getcmdline+0xf2 [c:\projects\sdl\src\main\windows\sdl_windows_main.c @ 177] 
0e (Inline Function) : --------`--------  : Cataclysm!invoke_main+0x21 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 94] 
0f 00007ffc`a85c81f4 : 00000000`00000000  : Cataclysm!__scrt_common_main_seh+0x117 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 253] 
10 00007ffc`a9fca251 : 00000000`00000000  : KERNEL32!BaseThreadInitThunk+0x14
11 00000000`00000000 : 00000000`00000000  : ntdll!RtlUserThreadStart+0x21

So in the source the error happens here.

Upon investigation we have (comments are mine):

    std::vector<point> new_mounts;
    new_vehicle->name = veh_record.substr( vehicle_part::name_offset ); // veh_record = "X  0  0Large Cart" ; new_vehicle->name = "Large Cart"
    for( auto carried_part : carried_parts ) {  // carried_parts = [0x23, 0x24, 0x26]
        std::string mount_str = parts[ carried_part ].carry_names.top().substr( 1, 3 );
        point new_mount;
        if( x_aligned ) {
            new_mount.x = std::stoi( mount_str );
        } else {
            new_mount.y = std::stoi( mount_str );
        }
        new_mounts.push_back( new_mount );
    }

Notice carried_parts is a std::vector with three values: [0x23, 0x24, 0x26].

All goes well for the two first ones, that is index 0x23 and 0x24 of parts (we are looking at parts[ carried_part ]):

[0x00000023] = {carry_names={ size=0x0000000000000001 } mount={x=0xfffffffe y=0x00000000 } precalc={ size=0x00000002 } ...}
[0x00000024] = {carry_names={ size=0x0000000000000001 } mount={x=0xfffffffe y=0x00000000 } precalc={ size=0x00000002 } ...}

For both of them the carry_names size is 1 (note: carry_names is a std::stack).

Upon entering the loop for the third element (0x26) and looking once again at parts[ carried_part ] we have:

[0x00000026] = {carry_names={ size=0x0000000000000000 } mount={x=0xfffffffe y=0x00000000 } precalc={ size=0x00000002 } ...}

As you can see carry_names is 0 / empty thus calling top() on an empty stack is not possible and the game crashes.

I'm not used to this part of the game so I don't know how to patch it, but I'm going to look at it if I can make sense of it.

mlangsdorf commented 5 years ago

Each part of a carried vehicle stores its mount location from when it was a separate vehicle in carry_names. This is required, because each part of a vehicle could be anywhere in the vehicle parts vector and there's no other way to tell where the carried part should go when you unmount the carried vehicle.

I'm guess the unicycle wheel was added to the unicycle while it was a carried vehicle, and didn't get a carry_names because those are assigned when the carried vehicle is loaded. I think something like this would work:

for( auto carried_part : carried_parts ) {
    point new_mount;
    std::string mount_str;
    if( !parts[ carried_part ].carry_names.empty() ) {
        mount_str = parts[ carried_part ].carry_names.top().substr( 1, 3 );
    } else {
        // check if any other parts at the same location have a valid carry name
        for( local_part: parts_at_relative( parts[ carried_part].mount, true ) {
            if( !parts[ local_part ].carry_names.empty() ) {
                mount_str = parts[ local_part ].carry_names.top().substr( 1, 3 );
                break;
            }
        }
    }
    if( mount_str.empty() ) {
        return false;
    }
    if( x_aligned ) {
        new_mount.x = std::stoi( mount_str );
    } else {
        new_mount.y = std::stoi( mount_str );
    }
    new_mounts.push_back( new_mount );
}

but I haven't tested it or anything.

Thanks for looking into this.

AndrasZodon commented 5 years ago

Not sure this was fixed. May be a different issue but it looks similar. Version: 0.D 9322 Win7 Tiles Mod List: "dda", "no_npc_food", "aftershock", "crt_expansion", "magiclysm", "craftgp", "FIC_Weapons", "growable-pots", "Medieval_Stuff", "More_Survival_Tools", "modular_turrets", "Salvaged_Robots", "fast_healing", "hydroponics", "more_locations", "Urban_Development", "FujiStruct", "deoxymod", "blazemod", "Tanks", "RL_Classes", "manualbionicinstall", "safeautodoc", "speedydex", "StatsThroughSkills"

https://i.imgur.com/up1RZlI.png Screenshot of Error text

https://www.dropbox.com/sh/90wmsgguucov143/AADmsWWEb2zQBWXel_e747eWa?dl=0

The save (cannot guarantee the longterm permanence of this link)

Solar bike racked onto rear end of custom armored van. The solar panels were added to the bike while it was attached, but it was able to detach without crashing multiple times after the modification. So, it worked previously, but now causes crashes 100% of the time when unloaded. Not sure when it started, but it may have been the last time I repaired damage dealt to the bike.

@mlangsdorf @ZhilkinSerg Edit edit: Nevermind on that edit, I'm dumb