Closed Necrosian closed 5 years ago
Could you please upload your save file? It would definitely help to understand what's going on. Thanks!
Did you do anything special when the crash happened? Anything you could think of could help to repro the bug and fix it.
你能上传你的保存文件吗?这肯定有助于了解正在发生的事情。谢谢!
事故发生时你做了什么特别的事吗?你能想到的任何东西都可以帮助重现bug并修复它。
this mistake is almost identical to what I have encountered. It should be ascend stairs. Part of the ascend stairs in the city makes this mistake. I can't tell where it will be, but I know.research facility are one of them. will be a crash
My English is not good. I hope you can understand it.
Could you please upload your save file? It would definitely help to understand what's going on. Thanks!
Did you do anything special when the crash happened? Anything you could think of could help to repro the bug and fix it.
Had several crashes before in couple minute intervals. Doing random things(looting, exploring, fighting) and it just crashed.
@Necrosian Many thanks :+1: I'll try to reproduce the bug on my side and keep you updated.
@ZikoWong Understood :+1: This could definitely help to track the bug down.
I was able to trigger the big on my side. With ZhilkinSerg's help I could confirm it's the same bug.
Sorry for the wall of text that follows.
Here'a a complete stack trace (see on the right for function names and source code files):
0:000> kb
# RetAddr : Args to Child : Call Site
00 00007ff6`c97f2bab : 00000023`313ac638 ffffffff`ffffffff 00000023`313ac5e8 00000023`313adb38 : Cataclysm!std::vector<maptile,std::allocator<maptile> >::operator[]+0x87 [d:\programming\microsoft visual studio 14.0\vc\include\vector @ 1235]
01 00007ff6`c97db8b6 : 00000023`313adab0 00000154`339c0a40 00000023`313adb38 00000000`0000002b : Cataclysm!<lambda_d68268ff737706d09db60fb4644b745b>::operator()+0x7bb [k:\cdda\cataclysm-dda\src\field.cpp @ 718]
02 00007ff6`c97d7e66 : 00000153`e77f69d0 00000154`0921c200 00000023`00000000 00007ff6`00000000 : Cataclysm!map::process_fields_in_submap+0x39f6 [k:\cdda\cataclysm-dda\src\field.cpp @ 1447]
03 00007ff6`c9819d4a : 00000153`e77f69d0 00000023`313ae7a8 00000023`313ae750 00000001`00000036 : Cataclysm!map::process_fields+0x146 [k:\cdda\cataclysm-dda\src\field.cpp @ 523]
04 00007ff6`c8ecb83a : 00000153`e77d6e30 00000000`00000338 00000000`0000003f 00000000`00000001 : Cataclysm!game::do_turn+0xbca [k:\cdda\cataclysm-dda\src\game.cpp @ 1462]
05 00007ff6`c8e301d2 : 00000153`00000000 00000153`e5ac0008 00000153`e3d92fcc 00000401`00000000 : Cataclysm!SDL_main+0x16fa [k:\cdda\cataclysm-dda\src\main.cpp @ 682]
06 00007ff6`cb1587fd : 00000000`00000000 00000000`00000000 00000000`00000000 00007ff6`cb57fe80 : Cataclysm!main_getcmdline+0xf2 [c:\projects\sdl\src\main\windows\sdl_windows_main.c @ 177]
07 00007ff6`cb1586c7 : 00007ff6`cb578000 00007ff6`cb57f930 00000000`00000000 00000000`00000000 : Cataclysm!invoke_main+0x2d [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 99]
08 00007ff6`cb15858e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : Cataclysm!__scrt_common_main_seh+0x127 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 253]
09 00007ff6`cb158819 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : Cataclysm!__scrt_common_main+0xe [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 296]
0a 00007ffc`a85c81f4 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : Cataclysm!WinMainCRTStartup+0x9 [f:\dd\vctools\crt\vcstartup\src\startup\exe_winmain.cpp @ 17]
0b 00007ffc`a9fca251 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14
0c 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21
This happens in the map::process_fields_in_submap function, exactly here
end_it = static_cast<size_t>( rng( 0, neighs.size() - 1 ) );
for( size_t i = ( end_it + 1 ) % neighs.size() ;
// Start at end_it + 1, then wrap around until i == end_it
i != end_it;
i = ( i + 1 ) % neighs.size() ) {
const auto &neigh = neighs[i];
if( ( neigh.x != remove_tile.x && neigh.y != remove_tile.y ) ||
( neigh.x != remove_tile2.x && neigh.y != remove_tile2.y ) ||
( neigh.x != remove_tile3.x && neigh.y != remove_tile3.y ) ) {
neighbour_vec.push_back( neigh );
}
}
spread_to( neighbour_vec[ rng( 0, neighbour_vec.size() - 1 ) ] ); // Crash here
So, neighbour_vec
is indexed but it's empty which leads to a crash.
The state of the local variables at time of crash:
0:000> dx Debugger.Sessions[0].Processes[22672].Threads[44860].Stack.Frames[1].SwitchTo();dv /t /v
Debugger.Sessions[0].Processes[22672].Threads[44860].Stack.Frames[1].SwitchTo()
00000023`313ac880 class map::process_fields_in_submap::__l2::<lambda_d68268ff737706d09db60fb4644b745b> * this = 0x00000023`313adab0
00000023`313ac888 class field_entry * cur = 0x00000154`339c0a40
00000023`313ac890 struct tripoint * p = 0x00000023`313adb38
00000023`313ac898 field_id curtype = fd_hot_air3 (0n43)
00000023`313ac8a0 int percent_spread = 0n100
00000023`313ac8a8 class time_duration * outdoor_age_speedup = 0x00000023`313acd9c
00000023`313ac530 unsigned int64 end_it = 7
00000023`313ac618 class std::vector<unsigned __int64,std::allocator<unsigned __int64> > spread = { size=0 }
00000023`313ac6d8 struct maptile remove_tile3 = struct maptile
00000023`313ac670 class map::process_fields_in_submap::__l2::<lambda_d68268ff737706d09db60fb4644b745b>::()::__l2::<lambda_c8a944397b3f668861a82793f7b7af54> spread_to = class map::process_fields_in_submap::__l2::<lambda_d68268ff737706d09db60fb4644b745b>::()::__l2::<lambda_c8a944397b3f668861a82793f7b7af54>
00000023`313ac520 bool sheltered = false
00000023`313ac5f0 class map::process_fields_in_submap::__l2::<lambda_d68268ff737706d09db60fb4644b745b>::()::__l2::<lambda_c4266a27ca14e405effa26e88c337faa> can_spread_to = class map::process_fields_in_submap::__l2::<lambda_d68268ff737706d09db60fb4644b745b>::()::__l2::<lambda_c4266a27ca14e405effa26e88c337faa>
00000023`313ac5e8 int winddirection = 0n270
00000023`313ac538 int windpower = 0n9
00000023`313ac588 class int_id<oter_t> * cur_om_ter = 0x00000154`00197950
00000023`313ac790 class std::array<maptile,8> neighs = { size=8 }
00000023`313ac5e0 int current_density = 0n3
00000023`313ac638 class std::vector<maptile,std::allocator<maptile> > neighbour_vec = { size=0 }
00000023`313ac6c0 struct maptile remove_tile2 = struct maptile
00000023`313ac740 class std::tuple<maptile,maptile,maptile> maptiles = class std::tuple<maptile,maptile,maptile>
00000023`313ac5e4 class time_duration current_age = class time_duration
00000023`313ac6a8 struct maptile remove_tile = struct maptile
The neigh
array has 8 elements:
0:000> dx -r1 (*((Cataclysm!std::array<maptile,8> *)0x23313ac790))
(*((Cataclysm!std::array<maptile,8> *)0x23313ac790)) : { size=8 } [Type: std::array<maptile,8>]
[<Raw View>] [Type: std::array<maptile,8>]
[0] [Type: maptile]
[1] [Type: maptile]
[2] [Type: maptile]
[3] [Type: maptile]
[4] [Type: maptile]
[5] [Type: maptile]
[6] [Type: maptile]
[7] [Type: maptile]
Below is the state of each of them (we are only interested on their x
and y
members):
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac790)) // index 0
(*((Cataclysm!maptile *)0x23313ac790)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac7a8)) // index 1
(*((Cataclysm!maptile *)0x23313ac7a8)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac7c0)) // index 2
(*((Cataclysm!maptile *)0x23313ac7c0)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac7d8)) // index 3
(*((Cataclysm!maptile *)0x23313ac7d8)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac7f0)) // index 4
(*((Cataclysm!maptile *)0x23313ac7f0)) [Type: maptile]
[+0x000] sm : 0x1540921c200 [Type: submap *]
[+0x008] x : 0x1 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac808)) // index 5
(*((Cataclysm!maptile *)0x23313ac808)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac820)) // index 6
(*((Cataclysm!maptile *)0x23313ac820)) [Type: maptile]
[+0x000] sm : 0x1540921c200 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x1 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac838)) // index 7
(*((Cataclysm!maptile *)0x23313ac838)) [Type: maptile]
[+0x000] sm : 0x1540921c200 [Type: submap *]
[+0x008] x : 0x1 [Type: unsigned __int64]
[+0x010] y : 0x1 [Type: unsigned __int64]
Given this comparison:
if( ( neigh.x != remove_tile.x && neigh.y != remove_tile.y ) ||
( neigh.x != remove_tile2.x && neigh.y != remove_tile2.y ) ||
( neigh.x != remove_tile3.x && neigh.y != remove_tile3.y ) ) {
neighbour_vec.push_back( neigh );
}
And the state of remove_tile
, remove_tile2
and remove_tile3
:
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac6a8)) // remove_tile
(*((Cataclysm!maptile *)0x23313ac6a8)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac6c0)) // remove_tile2
(*((Cataclysm!maptile *)0x23313ac6c0)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
0:000> dx -r1 (*((Cataclysm!maptile *)0x23313ac6d8)) // remove_tile3
(*((Cataclysm!maptile *)0x23313ac6d8)) [Type: maptile]
[+0x000] sm : 0x7ff6cc197590 [Type: submap *]
[+0x008] x : 0x0 [Type: unsigned __int64]
[+0x010] y : 0x0 [Type: unsigned __int64]
The comparison in the if
should match the last tile index 7 (which has x = 1
and y = 1
) and this tile should be pushed to the vector.
Edit
Now with this code for the processing loop:
for( size_t i = ( end_it + 1 ) % neighs.size() ;
i != end_it;
i = ( i + 1 ) % neighs.size() )
end_it
= 7 (given by the random generator just a bit above the code)i != end_it
) which is, in this case, i != 7
.Proposed patch: just check that the vector is not empty before indexing it.
Describe the bug
Had multiple crashes while looting a city
To Reproduce
I have no idea was walking/looting when last crash happened.
Expected behavior
Just crashes the game.
Screenshots
![crash](https://user-images.githubusercontent.com/26538192/55066562-bab87000-5086-11e9-890b-9071192513d8.PNG)
Versions and configuration(please complete the following information):
Additional context
Crash Log File:
CRASH LOG FILE: config/crash.log VERSION: 0.D-1042-ge3964f4 TYPE: Signal MESSAGE: SIGSEGV: Segmentation fault STACK TRACE: @0x555FB5[cataclysm-tiles.exe+0x155FB5] @0x556B62[cataclysm-tiles.exe+0x156B62] SMPEG_error+0x4B034@0xE280A0[cataclysm-tiles.exe+0xA280A0] _C_specific_handler+0x98@0x7FFAB31E8068[msvcrt.dll+0x28068] _chkstk+0x11F@0x7FFAB47F468F[ntdll.dll+0xA468F] RtlWalkFrameChain+0x14BF@0x7FFAB4754BEF[ntdll.dll+0x4BEF] KiUserExceptionDispatcher+0x2E@0x7FFAB47F33FE[ntdll.dll+0xA33FE] @0x60ACB3[cataclysm-tiles.exe+0x20ACB3] @0x60BB78[cataclysm-tiles.exe+0x20BB78] @0x611300[cataclysm-tiles.exe+0x211300] @0x618127[cataclysm-tiles.exe+0x218127] @0x682F4E[cataclysm-tiles.exe+0x282F4E] IMG_LoadWEBP_RW+0x4D91C9@0x13F30D9[cataclysm-tiles.exe+0xFF30D9] @0x4013ED[cataclysm-tiles.exe+0x13ED] @0x4014FB[cataclysm-tiles.exe+0x14FB] BaseThreadInitThunk+0x14@0x7FFAB1B581F4[KERNEL32.DLL+0x181F4] RtlUserThreadStart+0x21@0x7FFAB47BA251[ntdll.dll+0x6A251]
Edit: Uploaded a save zip.zip