使用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

