Skip to content

Commit beaeee3

Browse files
committed
Fix a case of static initialization order debacle
When descent3 is built with g++ -flto=auto, there is a crash at startup: ``` Program received signal SIGSEGV, Segmentation fault. 0x00005555557b3b20 in pilot::initialize ( this=this@entry=0x555555fbd480 <Current_pilot>) at Descent3/pilot_class.cpp:208 208 game_window_w = Video_res_list[Current_video_resolution_id].width; Missing separate debuginfos, use: zypper install libcpp-httplib0_20-debuginfo-0.20.1-2.1.x86_64 libSDL3-0-debuginfo-3.2.16-1.1.x86_64 libzstd1-x86-64-v3-debuginfo-1.5.7-3.1.x86_64 (gdb) p Current_video_resolution_id $1 = 0 (gdb) p Video_res_list $2 = std::vector of length 0, capacity 0 (gdb) bt f0 pilot::initialize (this=this@entry=0x555555fbd480 <Current_pilot>) at Descent3/pilot_class.cpp:208 f1 pilot::pilot (this=<optimized out>, this=<optimized out>) at Descent3/pilot_class.cpp:177 f2 _sub_I_65535_0.0 () f3 call_init (argc=1, argv=0x7fffffffdb68, env=<optimized out>) at ../csu/libc-start.c:145 f4 __libc_start_main_impl f5 _start () at ../sysdeps/x86_64/start.S:115 ``` When ASAN/UBSAN is enabled in conjunction with LTO: ``` /usr/include/c++/14/bits/stl_vector.h:1144:34: runtime error: reference binding to null pointer of type 'struct value_type' Descent3/pilot_class.cpp:208:63: runtime error: member access within null pointer of type 'struct value_type' AddressSanitizer:DEADLYSIGNAL ================================================================= ==58724==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 ==58724==The signal is caused by a READ memory access. ==58724==Hint: address points to the zero page. f0 pilot::initialize() Descent3/pilot_class.cpp:208 f1 pilot::pilot() Descent3/pilot_class.cpp:177 f2 _sub_I_65535_0.0 (b/build/Descent3+0x52ece3) f3 call_init ../csu/libc-start.c:145 f4 __libc_start_main_impl ../csu/libc-start.c:347 f5 _start ../sysdeps/x86_64/start.S:115 ``` ``_sub_I_65535_0.0`` is indicative of a global constructor, so we are looking at a case of Static Initialization Order Fiasco whereby ``pilot::initialize`` runs before ``Video_res_list`` and ``Current_resolution_id`` get initialized. Perform pilot construction explicitly in main(). Fixes: 40c7f0d
1 parent da7cdf0 commit beaeee3

4 files changed

Lines changed: 9 additions & 3 deletions

File tree

Descent3/pilot.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,11 @@ void PilotShutdown() {
696696
Current_pilot.clean(false);
697697
}
698698

699+
void PilotEarlyInit()
700+
{
701+
Current_pilot.initialize();
702+
}
703+
699704
void PilotInit() {
700705
PilotInitData(&Current_pilot);
701706
atexit(PilotShutdown);

Descent3/pilot_class.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,9 @@ pilot::pilot() :
177177
hud_mode{HUD_COCKPIT},
178178
hud_graphical_stat{STAT_STANDARD}
179179
{
180-
initialize();
181180
}
182181

183-
// initializes all the data (for constructors)
182+
// Two-stage construction (because it references global vars)
184183
void pilot::initialize(void) {
185184
int i;
186185

Descent3/pilot_class.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ class pilot {
233233
void get_mission_data(int index, tMissionData *data);
234234
int find_mission_data(const char *mission_name);
235235

236-
private:
237236
void initialize(void); // initializes all the data (for constructors)
237+
private:
238238
bool write_pending = false; // data has changed and pilot data is out of sync with file
239239
private:
240240
// internal file access functions

Descent3/sdlmain.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "init.h"
4646
#include "log.h"
4747
#include "config.h"
48+
#include "pilot.h"
4849

4950
#ifdef WIN32
5051
#include "debug.h"
@@ -222,6 +223,7 @@ int main(int argc, char *argv[]) {
222223
GatherArgs(argv);
223224
bool enable_winconsole = true;
224225
#endif
226+
Current_pilot.initialize();
225227

226228
orig_pwd = std::filesystem::current_path();
227229

0 commit comments

Comments
 (0)