Fix an MSVC debug break

With the latest master I started getting:
"A breakpoint instruction (__debugbreak() statement or a similar call) was executed in Stockfish.exe." when debugging in MSVC.

I don't really understand the issue but Fable fixed it and I verified it works.
Here is its summary:
Bug: Calling _get_wpgmptr() in CommandLine::get_binary_directory() triggered a debug CRT assertion failure (__debugbreak()) on Windows. The CRT only initializes the wide program name _wpgmptr when the application uses a wide entry point (wmain). Since Stockfish uses the narrow main(int, char**) entry point, _wpgmptr remains nullptr, and the debug CRT's parameter validation asserts when _get_wpgmptr is called.

Fix: Replaced _get_wpgmptr() with GetModuleFileNameW(), which queries the executable path directly from the OS and does not depend on the CRT entry point type. The implementation uses a grow-and-retry loop, so paths longer than MAX_PATH are handled correctly. If the API fails, the code falls back to the original argv0-based behavior. The #ifdef _MSC_VER guard was also removed, since the fix no longer relies on the MSVC CRT — non-MSVC Windows builds (e.g., MinGW) now benefit from the accurate path as well.

closes https://github.com/official-stockfish/Stockfish/pull/6972

No functional change
This commit is contained in:
mstembera
2026-07-16 08:28:08 +02:00
committed by Joost VandeVondele
parent ca11d43709
commit 057e9bf4da
+9 -6
View File
@@ -577,12 +577,15 @@ bool is_whitespace(std::string_view s) {
fs::path CommandLine::get_binary_directory(fs::path argv0) { fs::path CommandLine::get_binary_directory(fs::path argv0) {
#ifdef _WIN32 #ifdef _WIN32
#ifdef _MSC_VER // Prefer the executable path reported by Windows. Unlike _get_wpgmptr,
// Prefer the executable path reported by the CRT when available. // this does not depend on whether the CRT used a narrow or wide entry
wchar_t* pgmptr = nullptr; // point. Windows paths cannot exceed 32767 characters, so a fixed
if (!_get_wpgmptr(&pgmptr) && pgmptr != nullptr && *pgmptr) // buffer is always sufficient. Falls back to argv0 if the API fails.
argv0 = fs::path(pgmptr); constexpr DWORD MaxPath = 32768;
#endif wchar_t path[MaxPath];
if (const DWORD length = GetModuleFileNameW(nullptr, path, MaxPath))
argv0 = fs::path(path, path + length);
#endif #endif
auto binaryDirectory = argv0.parent_path(); auto binaryDirectory = argv0.parent_path();