fix qtfred heap corruption in FastDebug builds#7450
Merged
Conversation
FastDebug FSO compiled with /MDd (debug CRT) but imported Qt's Release
libraries via CMAKE_MAP_IMPORTED_CONFIG_FASTDEBUG = Release Debug. Qt
Release ships /MD, so any allocation crossing the qtfred <-> Qt boundary
went into one heap and came back out of the other, tripping
_CrtIsValidHeapPointer on a perfectly-valid std::string dtor. Latent for
ages because it only surfaces when an allocation actually crosses;
opening a mission file is one such path.
To paper over the resulting STL layout difference, FastDebug also forced
_ITERATOR_DEBUG_LEVEL=0 so qtfred's std::string matched Release Qt's.
Not needed once we link Debug Qt, and keeping it would introduce a fresh
mismatch (qtfred IDL=0 vs Debug Qt IDL=2).
Fix:
- Map FastDebug imports to "Debug Release \"\"" in qtfred/CMakeLists.
Debug picks Qt's debug libs; Release is a defensive fallback; the
empty entry falls back to plain IMPORTED_LOCATION, required because
Qt's host tools (uic/moc/rcc/qhelpgenerator) ship a single variant
with no IMPORTED_LOCATION_<CONFIG>. Must precede find_package(Qt5):
CMake snapshots the variable into each target's MAP_IMPORTED_CONFIG
property at creation time. (Also why the prior "Release Debug" was
silently a no-op -- set after find_package, ignored; CMake fell
back to Release on its own.)
- Extend the qwindows/qsqlite plugin POST_BUILD copies' "d"-suffix
generator expression to match FastDebug as well as Debug, so the
Debug Qt runtime finds qwindowsd.dll / qsqlited.dll alongside.
- Drop the FastDebug-only _ITERATOR_DEBUG_LEVEL=0 from the MSVC
toolchain file. Qt was the sole consumer; pure-C deps don't care.
Cost: FastDebug STL containers pick up MSVC's debug-iterator overhead.
Reasonable trade for a config named "Debug with optimizations".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
wookieejedi
approved these changes
May 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
FastDebug FSO compiled with /MDd (debug CRT) but imported Qt's Release libraries via CMAKE_MAP_IMPORTED_CONFIG_FASTDEBUG = Release Debug. Qt Release ships /MD, so any allocation crossing the qtfred <-> Qt boundary went into one heap and came back out of the other, tripping _CrtIsValidHeapPointer on a perfectly-valid std::string dtor. Latent for ages because it only surfaces when an allocation actually crosses; opening a mission file is one such path.
To paper over the resulting STL layout difference, FastDebug also forced _ITERATOR_DEBUG_LEVEL=0 so qtfred's std::string matched Release Qt's. Not needed once we link Debug Qt, and keeping it would introduce a fresh mismatch (qtfred IDL=0 vs Debug Qt IDL=2).
Fix:
Cost: FastDebug STL containers pick up MSVC's debug-iterator overhead. Reasonable trade for a config named "Debug with optimizations".