C语言递归遍历目录时sprintf_s触发Access Violation求助
遍历目录时sprintf_s触发Access Violation错误
我是C语言新手,想遍历指定目录及其子目录,记录文件名和最后访问时间,但每次调用sprintf_s()后都会触发Access Violation错误,怀疑和递归函数的指针参数有关。
原代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<windows.h> #include<direct.h> #include<stdbool.h> #define __STDC_WANT_LIB_EXT1__ 1 bool ListFromDirectory(const char* sDir) {//递归遍历目录的函数 WIN32_FIND_DATA fdFile; HANDLE hFind = NULL; char sPath[2048]; //指定文件掩码 *.* sprintf_s(sPath, "%s\\*.*", sDir); if ((hFind = FindFirstFile(sPath, &fdFile)) == INVALID_HANDLE_VALUE) { printf("Path not found: [%s]\n", sDir); return false; } do { //FindFirstFile总会先返回"."和".."两个目录 if (strcmp(fdFile.cFileName, ".") != 0 && strcmp(fdFile.cFileName, "..") != 0) { LPSYSTEMTIME lpSystemTime; //判断是文件还是文件夹 if (fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { printf("Directory: %s\n", sPath); ListFromDirectory(sPath); } else { printf("File: %ls\n", fdFile.cFileName); FILETIME localFiletime; if (FileTimeToLocalFileTime(&fdFile.ftLastWriteTime, &localFiletime)) { SYSTEMTIME sysTime; if (FileTimeToSystemTime(&localFiletime, &sysTime)) { printf("%ls is last modified at %.2d-%.2d-%4d %.2d:%.2d:%.2d\n", fdFile.cFileName, sysTime.wMonth, sysTime.wDay, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond); } } } } } while (FindNextFile(hFind, &fdFile)); //查找下一个文件 FindClose(hFind); return true; } int main() { char c[12] = "E:\\Windows\\"; ListFromDirectory(c); return 0; }
错误信息
sprintf_s()执行后触发异常:Exception thrown at 0x7A85EF8C (ucrtbased.dll): 0xC0000005: Access violation writing location 0x00760000。
问题根源
- 递归传入错误路径:处理子目录时,你传入的是带
*.*的sPath(如E:\Windows\*.*),而非子目录的完整路径,导致后续递归中sprintf_s处理非法路径,引发内存访问错误。 - 字符编码混用:未定义
UNICODE时,WIN32_FIND_DATA的cFileName是多字节字符串,但你用%ls(宽字符格式符)打印,会导致输出乱码,还可能间接引发内存问题。 - 冗余未初始化指针:代码中声明了
LPSYSTEMTIME lpSystemTime;但从未使用,属于不良编码习惯。
修复后的代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<windows.h> #include<direct.h> #include<stdbool.h> #define __STDC_WANT_LIB_EXT1__ 1 bool ListFromDirectory(const char* sDir) { WIN32_FIND_DATA fdFile; HANDLE hFind = NULL; char sPath[2048]; // 拼接搜索路径,显式传入缓冲区大小 sprintf_s(sPath, sizeof(sPath), "%s\\*.*", sDir); if ((hFind = FindFirstFile(sPath, &fdFile)) == INVALID_HANDLE_VALUE) { printf("路径未找到: [%s]\n", sDir); return false; } do { if (strcmp(fdFile.cFileName, ".") != 0 && strcmp(fdFile.cFileName, "..") != 0) { // 拼接当前文件/子目录的完整路径 char fullPath[2048]; sprintf_s(fullPath, sizeof(fullPath), "%s\\%s", sDir, fdFile.cFileName); if (fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { printf("目录: %s\n", fullPath); // 递归传入子目录的合法完整路径 ListFromDirectory(fullPath); } else { printf("文件: %s\n", fdFile.cFileName); FILETIME localFiletime; // 替换为最后访问时间(而非修改时间) if (FileTimeToLocalFileTime(&fdFile.ftLastAccessTime, &localFiletime)) { SYSTEMTIME sysTime; if (FileTimeToSystemTime(&localFiletime, &sysTime)) { printf("%s 最后访问时间: %.2d-%.2d-%4d %.2d:%.2d:%.2d\n", fdFile.cFileName, sysTime.wMonth, sysTime.wDay, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond); } } } } } while (FindNextFile(hFind, &fdFile)); FindClose(hFind); return true; } int main() { char c[12] = "E:\\Windows\\"; ListFromDirectory(c); return 0; }
关键修复点
- 递归调用时传入拼接好的子目录完整路径,而非带通配符的搜索路径。
- 统一用
%s打印多字节字符串,避免编码格式不匹配问题。 - 将
ftLastWriteTime替换为ftLastAccessTime,满足记录最后访问时间的需求。 - 移除未使用的冗余指针,调用
sprintf_s时显式传入缓冲区大小,提升代码安全性。
内容的提问来源于stack exchange,提问作者wngm_889
相关产品推荐
相关产品推荐

