MINGW64中带\\?\前缀的超长路径下_wstat失效问题
问题:MinGW编译下
_wstat无法识别带\\?\前缀的长路径文件 问题描述
某C程序需用stat系列函数检查文件是否存在,因目标路径可能超过MAX_PATH(260字符),采用Windows官方推荐的\\?\长路径前缀,同时使用wchar_t*支持特殊字符。使用MSVC 19编译时,_wstat可正常找到\\?\D:\path\to\test.txt文件;但用MINGW64(gcc 12.2,Windows 11环境)编译相同程序时,_wstat调用失败,提示文件未找到。
复现步骤
- 编写
main.c文件:
#include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <errno.h> #include <wchar.h> int main(void) { //wchar_t* unicodeLongFileName = L"D:\\path\\to\\test.txt"; // 可正常运行 wchar_t* unicodeLongFileName = L"\\\\?\\D:\\path\\to\\test.txt"; // 修正转义后的路径,MinGW下仍失效 struct _stat statbuf; int res = _wstat(unicodeLongFileName, &statbuf); if (res != 0) { perror( "Problem getting information" ); switch (errno) { case ENOENT: wprintf(L"File \n%ls\n not found.\n", unicodeLongFileName); break; case EINVAL: printf("Invalid parameter to _stat.\n"); break; default: printf("Unexpected error in _stat.\n"); } return -1; } wprintf(L"Found file \n%ls\n.\n", unicodeLongFileName); return 0; }
注:原代码中字符串字面量存在转义错误,正确转义应为
L"\\\\?\\D:\\path\\to\\test.txt",但即使修正后,MinGW下依然会出现问题。
- 编写
CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.20) project(Test_wstat) add_executable(Test_wstat main.c)
- 编译:
- MSVC版本:
cmake -S . -B build_msvc cmake --build build_msvc/ --config Release- MINGW64版本:
cmake -S . -B build_mingw -G "MSYS Makefiles" -DCMAKE_C_COMPILER=gcc -Wno-dev make -C build_mingw/ all -Oline - 运行:
- 创建测试文件:
touch /d/path/to/test.txt - MSVC编译程序:正常找到目标文件
- MINGW64编译程序:提示文件未找到
- 创建测试文件:
原因分析
MinGW-w64的C运行时库(CRT)中,_wstat的实现基于POSIX兼容层的路径处理逻辑,并未完全适配Windows特有的\\?\长路径前缀;而MSVC的CRT直接调用Windows原生API,完全支持该前缀的解析。
解决方案
方案一:使用Windows原生API替代_wstat
直接调用Windows的GetFileAttributesW函数,该函数原生支持\\?\前缀,可直接判断文件是否存在:
#include <windows.h> #include <wchar.h> #include <stdio.h> int main(void) { wchar_t* unicodeLongFileName = L"\\\\?\\D:\\path\\to\\test.txt"; DWORD attr = GetFileAttributesW(unicodeLongFileName); if (attr == INVALID_FILE_ATTRIBUTES) { DWORD err = GetLastError(); if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) { wprintf(L"File \n%ls\n not found.\n", unicodeLongFileName); } else { wprintf(L"Error accessing file: %lu\n", err); } return -1; } wprintf(L"Found file \n%ls\n.\n", unicodeLongFileName); // 若需获取更多文件信息,可使用GetFileInformationByHandle等API return 0; }
编译时无需额外选项,MinGW可正常链接kernel32.lib。
方案二:让MinGW的_wstat支持长路径
若坚持使用_wstat,可尝试以下操作:
- 定义
_WIN32_WINNT宏为0x0601(Windows 7及以上版本),启用长路径支持:
在CMakeLists.txt中添加:target_compile_definitions(Test_wstat PRIVATE _WIN32_WINNT=0x0601) - 使用
_wstat64替代_wstat,MinGW的64位版本对长路径的支持更完善:
将代码中的struct _stat改为struct _stat64,_wstat改为_wstat64。
不过该方案的兼容性不如直接调用Windows API可靠。
内容的提问来源于stack exchange,提问作者AnHeuermann
相关产品推荐
相关产品推荐

