CNA-BUG-091: GameWindow keeps a raw pointer to the platform window owned by the Game's GraphicsDevice, and nothing clears it when the game disposes that device
Evidence basis: source-verified at the pinned commit. Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
Game's constructor hands GraphicsDevice_.GetPlatformWindowInternal() to Window_.setWindowInternal; GraphicsDevice::Dispose destroys the platform window (destroyNativeResources resets platformWindow_), after which GameWindow members dereference freed memory.
- Identifier
CNA-BUG-091- Category
- Bug
- Subsystem
- Core & runtime
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- None
- Affected contract
- Microsoft::Xna::Framework::GameWindow members after an explicit GraphicsDevice::Dispose() on the Game's device
Expected behaviour
A borrowed pointer must not outlive its owner; either GameWindow should be detached when the device destroys its window, or the device must not destroy a window the Game still exposes.
Actual behaviour at TARGET
In Game.cpp the constructor calls Window_.setWindowInternal(GraphicsDevice_.GetPlatformWindowInternal(), ...). GameWindow.cpp stores it in window_ and uses it for Title, AllowUserResizing, IsBorderless, ClientBounds, Handle and the rest. GraphicsDevice.cpp's destroyNativeResources (called by Dispose) resets the owning std::unique_ptr<IPlatformWindow>. Nothing rebinds or clears GameWindow::window_, so after a game disposes its device (the manager comments note "A game may explicitly dispose its device from Draw()") the next Window property call touches freed memory.
Source locations
modules/runtime/src/Game.cpp— Game constructor: Window_.setWindowInternal(...)modules/runtime/src/GameWindow.cpp— GameWindow::setWindowInternal and the window_ usersmodules/graphics/src/Xna/GraphicsDevice.cpp— GraphicsDevice::destroyNativeResources (platformWindow_.reset())
Evidence
Checked by reading the named sources at 009d40f5; nothing was built or executed for this entry. The GraphicsDeviceManager guards its own frame lease against this (its Disposing handler); GameWindow has no equivalent.
Focused reproduction
// Illustrative; not compiled or run for this entry.
protected: void Draw(const GameTime& t) override {
getGraphicsDeviceProperty().Dispose(); // explicit device disposal
Exit();
}
// later in the same run: getWindowProperty().setTitleProperty("...") or ClientBounds -> freed IPlatformWindow
Current tests
No test disposes the Game's device and then uses the window.
Regression test
An ASan test that disposes the Game's GraphicsDevice and then reads Window.ClientBounds (expecting a defined result or an ObjectDisposedException).
Blast radius
Games that explicitly dispose their GraphicsDevice before the Game ends; the normal shutdown order is unaffected.
Workaround
Do not dispose the Game's GraphicsDevice yourself; let the Game own it.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- Runtime shutdown: device
- Deep dives
- Window and device manager: GameWindow
- Known issues
- Bug index