Skip to content

Commit afda9cb

Browse files
committed
Fix: ManualRender RunnerParams lifetime management
Fixes segfault when using ManualRender with SetupFromSimpleRunnerParams() or SetupFromGuiFunction(). After changing SetupFromRunnerParams() to keep a reference instead of a copy, the temporary RunnerParams created in these functions would go out of scope, leaving a dangling pointer. Changes: - Add gStoredRunnerParams to store RunnerParams when created internally - Store RunnerParams in SetupFromSimpleRunnerParams() before passing reference - Store RunnerParams in SetupFromGuiFunction() before passing reference - Clear stored params in Priv_TearDown() for proper cleanup - Remove obsolete gLastRunnerParamsOpt (no longer needed after #417 fix) This mirrors the pattern used in ImmApp and ensures RunnerParams lifetime is managed correctly for both user-provided and internally-created params. Fixes segfault in hello_imgui.nb.start() on desktop platforms. Related: #417
1 parent 8f4d797 commit afda9cb

1 file changed

Lines changed: 11 additions & 4 deletions

File tree

src/hello_imgui/impl/hello_imgui.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ bool _CheckAdditionLayoutNamesUniqueness(const RunnerParams &runnerParams)
5555
// gLastRunnerParamsUserPointer contains a pointer to the user's runnerParams
5656
// This is used for both Run() and ManualRender::SetupFromRunnerParams()
5757
static RunnerParams* gLastRunnerParamsUserPointer = nullptr;
58+
// gStoredRunnerParams stores a copy of RunnerParams when created from SimpleRunnerParams or GuiFunction
59+
// This is necessary because SetupFromRunnerParams keeps a pointer to the runnerParams,
60+
// so we need to keep it alive between Setup and TearDown
61+
static std::optional<RunnerParams> gStoredRunnerParams;
5862
// a pointer to the current AbstractRunner
5963
static std::unique_ptr<AbstractRunner> gLastRunner;
6064

@@ -127,6 +131,7 @@ static void Priv_TearDown()
127131
gLastRunner = nullptr;
128132
gRendererInstanceCount = 0;
129133
gLastRunnerParamsUserPointer = nullptr;
134+
gStoredRunnerParams.reset(); // Clear the stored RunnerParams
130135
}
131136

132137

@@ -171,8 +176,9 @@ namespace ManualRender
171176
void SetupFromSimpleRunnerParams(const SimpleRunnerParams& simpleParams)
172177
{
173178
TrySwitchToInitialized();
174-
RunnerParams fullParams = simpleParams.ToRunnerParams();
175-
Priv_SetupRunner(fullParams, SetupMode::Renderer);
179+
// Store the runnerParams to keep it alive for the entire lifecycle
180+
gStoredRunnerParams = simpleParams.ToRunnerParams();
181+
Priv_SetupRunner(gStoredRunnerParams.value(), SetupMode::Renderer);
176182
}
177183

178184
// Initializes the renderer with a simple GUI function and additional parameters.
@@ -195,8 +201,9 @@ namespace ManualRender
195201
params.windowSize = windowSize;
196202
params.fpsIdle = fpsIdle;
197203
params.topMost = topMost;
198-
RunnerParams fullParams = params.ToRunnerParams();
199-
Priv_SetupRunner(fullParams, SetupMode::Renderer);
204+
// Store the runnerParams to keep it alive for the entire lifecycle
205+
gStoredRunnerParams = params.ToRunnerParams();
206+
Priv_SetupRunner(gStoredRunnerParams.value(), SetupMode::Renderer);
200207
}
201208

202209
// Renders the current frame. Should be called regularly to maintain the application's responsiveness.

0 commit comments

Comments
 (0)