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

使用C语言搜索目录及子目录字符串遇错误:返回码3221225725且无输出

目录字符串搜索代码崩溃问题排查

你编写的C语言代码用于在指定目录中搜索字符串,针对testdir目录及其中的.txt文件检索,但运行后返回值为3221225725(Windows平台下代表程序因非法内存访问崩溃),且无任何输出结果。目标文件夹与main.c位于同一目录,以下是代码问题排查及修复方案:

代码中的关键问题

1. 缺少必要头文件

strrchr、strstr等字符串操作函数需要<string.h>头文件,代码未包含会导致函数隐式声明,引发未定义行为。

2. 函数未声明就调用

searchDirectoryForString在main中调用,但调用前未声明或定义,编译器会默认其返回int类型,与实际void返回类型不匹配,触发运行错误。

3. opendir失败未处理

若opendir(dname)打开目录失败(如目录不存在、权限不足),返回的dp为NULL,后续readdir(dp)会访问空指针直接崩溃。

4. stat调用路径错误

stat(file->d_name, &filestat)中,file->d_name是相对当前进程工作目录的路径,而非当前遍历目录dname的相对路径。比如遍历testdir时,里面的a.txt会被当作当前目录下的文件查找,导致stat失败,文件类型判断无效。

5. 字符串比较逻辑错误

getFileExtension(file->d_name) == "txt"是指针地址比较,而非字符串内容比较,永远无法匹配.txt文件,应使用strcmp函数。

6. 野指针调用close

处理目录项时,若为目录或非.txt文件,fp未被fopen初始化(为野指针),此时调用close(fp)会触发非法内存访问崩溃。

7. 未排除.和..目录

遍历目录时会得到当前目录(.)和父目录(..),递归调用会进入无限循环,导致栈溢出崩溃。

8. 行号未按文件重置

lineno定义在函数开头,遍历多个文件时不会重置,导致后续文件行号从之前的累加值继续计数,不符合预期。

9. fopen失败未处理

若fopen打开文件失败(如权限问题、路径错误),返回的fp为NULL,后续fgets访问空指针会引发崩溃。

修复后的代码

#include <dirent.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>  // 新增必要头文件

// 提前声明函数,避免隐式声明
void searchDirectoryForString(char *dname, char *str);

int main(int argc, char *argv[])
{
    searchDirectoryForString("testdir", "Mathematics");
    return 0;
}

const char *getFileExtension(const char *filename)
{
    const char *dot = strrchr(filename, '.');
    if (!dot || dot == filename)
        return "";
    return dot + 1;
}

void searchDirectoryForString(char *dname, char *str)
{
    int resultoccr = 0;
    DIR *dp;
    FILE *fp = NULL;  // 初始化fp为NULL
    struct dirent *file;
    char temp[2048];
    char full_path[4096];  // 存储文件/子目录的完整路径

    dp = opendir(dname);
    if (dp == NULL) {  // 处理目录打开失败的情况
        printf("无法打开目录: %s\n", dname);
        return;
    }

    struct stat filestat;

    while ((file = readdir(dp)) != NULL)
    {
        // 跳过当前目录和父目录,避免无限递归
        if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) {
            continue;
        }

        // 拼接完整路径:dname + "/" + file->d_name
        snprintf(full_path, sizeof(full_path), "%s/%s", dname, file->d_name);

        if (stat(full_path, &filestat) == -1) {  // 处理stat失败的情况
            printf("无法获取文件信息: %s\n", full_path);
            continue;
        }

        if (S_ISDIR(filestat.st_mode))
        {
            // 递归处理子目录,传入完整路径
            searchDirectoryForString(full_path, str);
        }
        else if (S_ISREG(filestat.st_mode))
        {
            fp = fopen(full_path, "r");
            if (fp == NULL) {  // 处理文件打开失败的情况
                printf("无法打开文件: %s\n", full_path);
                continue;
            }

            // 用strcmp比较扩展名内容
            if (strcmp(getFileExtension(file->d_name), "txt") == 0)
            {
                int lineno = 1;  // 每个文件单独初始化行号
                // 文件搜索
                while (fgets(temp, 2048, fp) != NULL)
                {
                    if ((strstr(temp, str)) != NULL)
                    {
                        printf("找到目标: 文件%s 第%d行\t%s", full_path, lineno, temp);
                        resultoccr++;
                    }
                    lineno++;
                }
            }
            fclose(fp);  // 打开文件后才关闭,避免野指针
            fp = NULL;  // 重置fp为NULL
        }
    }
    closedir(dp);  // 关闭目录句柄,避免资源泄漏

    if (resultoccr == 0)
    {
        printf("目录%s中未找到目标字符串\n", dname);
    }
}

修复说明

  • 新增<string.h>头文件,解决字符串函数未定义问题。
  • 提前声明searchDirectoryForString函数,避免隐式声明错误。
  • 处理opendir、stat、fopen的失败情况,避免空指针访问。
  • 拼接完整路径,解决stat和fopen的路径错误问题。
  • 用strcmp比较字符串内容,替换指针比较逻辑。
  • 跳过.和..目录,避免无限递归。
  • 每个文件单独初始化lineno,保证行号计数正确。
  • 仅在打开文件后调用fclose,避免野指针操作崩溃。
  • 新增closedir(dp),关闭目录句柄避免资源泄漏。

内容的提问来源于stack exchange,提问作者user20137453

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 14:30:53