You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。


问题根源

  1. 递归传入错误路径:处理子目录时,你传入的是带*.*的sPath(如E:\Windows\*.*),而非子目录的完整路径,导致后续递归中sprintf_s处理非法路径,引发内存访问错误。
  2. 字符编码混用:未定义UNICODE时,WIN32_FIND_DATA的cFileName是多字节字符串,但你用%ls(宽字符格式符)打印,会导致输出乱码,还可能间接引发内存问题。
  3. 冗余未初始化指针:代码中声明了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 15:23:07