Skip to content

Commit 1a34123

Browse files
Goober5000claude
andauthored
fix qtfred heap corruption in FastDebug builds (scp-fs2open#7450)
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>
1 parent 2046f9b commit 1a34123

2 files changed

Lines changed: 16 additions & 7 deletions

File tree

cmake/toolchain-msvc.cmake

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ if(IS_X86)
114114

115115
endif()
116116

117-
add_compile_definitions("$<$<CONFIG:FastDebug>:_ITERATOR_DEBUG_LEVEL=0>")
118117
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
119118

120119
if (FSO_FATAL_WARNINGS)

qtfred/CMakeLists.txt

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ SET(QT5_INSTALL_ROOT "" CACHE PATH
88

99
list(APPEND CMAKE_PREFIX_PATH "${QT5_INSTALL_ROOT}")
1010

11+
# Must be set before find_package -- CMake snapshots this into each imported target's
12+
# MAP_IMPORTED_CONFIG_FASTDEBUG property at target-creation time, not at link time.
13+
# The list entries are tried in order:
14+
# "Debug" -- matches the per-config IMPORTED_LOCATION_DEBUG on Qt's libraries.
15+
# "Release" -- per-config fallback if any target ships only a Release variant.
16+
# "" -- the empty entry means "fall back to the suffix-less IMPORTED_LOCATION".
17+
# Required because Qt's host tools (uic/moc/rcc/qhelpgenerator) set
18+
# only IMPORTED_LOCATION (no IMPORTED_CONFIGURATIONS), so without this
19+
# CMake errors with "IMPORTED_LOCATION not set for imported target
20+
# Qt5::uic configuration FastDebug".
21+
set(CMAKE_MAP_IMPORTED_CONFIG_FASTDEBUG Debug Release "")
22+
1123
find_package(Qt5 COMPONENTS Widgets OpenGL Help REQUIRED)
1224

1325
include(source_groups.cmake)
@@ -51,8 +63,6 @@ if(WIN32)
5163
set_property(TARGET qtfred PROPERTY QT5_NO_LINK_QTMAIN ON)
5264
endif()
5365

54-
set(CMAKE_MAP_IMPORTED_CONFIG_FASTDEBUG Release Debug)
55-
5666
target_link_libraries(qtfred
5767
PUBLIC
5868
code
@@ -169,11 +179,11 @@ if (WIN32)
169179

170180
# Windows requires that the qwindows DLL is copied as well
171181
execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_PLUGINS OUTPUT_VARIABLE QT_INSTALL_PLUGINS OUTPUT_STRIP_TRAILING_WHITESPACE)
172-
set(qwindows_path "${QT_INSTALL_PLUGINS}/platforms/qwindows$<$<CONFIG:Debug>:d>.dll")
182+
set(qwindows_path "${QT_INSTALL_PLUGINS}/platforms/qwindows$<$<OR:$<CONFIG:Debug>,$<CONFIG:FastDebug>>:d>.dll")
173183

174184
add_custom_command(TARGET qtfred
175185
POST_BUILD
176-
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${qwindows_path}" "$<TARGET_FILE_DIR:qtfred>/platforms/qwindows$<$<CONFIG:Debug>:d>.dll"
186+
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${qwindows_path}" "$<TARGET_FILE_DIR:qtfred>/platforms/qwindows$<$<OR:$<CONFIG:Debug>,$<CONFIG:FastDebug>>:d>.dll"
177187
VERBATIM)
178188

179189
install(FILES ${qwindows_path}
@@ -182,11 +192,11 @@ if (WIN32)
182192
)
183193

184194
# Qt Help requires the SQLite SQL driver
185-
set(qsqlite_path "${QT_INSTALL_PLUGINS}/sqldrivers/qsqlite$<$<CONFIG:Debug>:d>.dll")
195+
set(qsqlite_path "${QT_INSTALL_PLUGINS}/sqldrivers/qsqlite$<$<OR:$<CONFIG:Debug>,$<CONFIG:FastDebug>>:d>.dll")
186196

187197
add_custom_command(TARGET qtfred
188198
POST_BUILD
189-
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${qsqlite_path}" "$<TARGET_FILE_DIR:qtfred>/sqldrivers/qsqlite$<$<CONFIG:Debug>:d>.dll"
199+
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${qsqlite_path}" "$<TARGET_FILE_DIR:qtfred>/sqldrivers/qsqlite$<$<OR:$<CONFIG:Debug>,$<CONFIG:FastDebug>>:d>.dll"
190200
VERBATIM)
191201

192202
install(FILES ${qsqlite_path}

0 commit comments

Comments
 (0)