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

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

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

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.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index