C语言多线程解析文本文件单词无法读取内容问题求助
问题原因及修复方案
核心问题1:文件路径错误
你调用opendir(argv[1])打开的是指定目录,但readdir返回的d_name仅为文件名本身,不包含目录前缀。你直接把文件名传给fopen时,程序只会在当前运行的工作目录下查找文件,不会去你指定的目标目录查找。
你输出中能打开文件,说明当前工作目录刚好存在同名的空文件,因此fgets读不到任何内容,单词打印逻辑自然不会执行。
核心问题2:线程逻辑存在未定义行为
你定义的线程数组pthread_t threads[threadCount]长度为你输入的线程数,但后续pthread_join时循环次数是目录内总文件数i:
- 如果目录内文件数大于线程数,会发生数组越界访问,且后续文件没有创建线程却执行
join操作,触发未定义行为 - 超出线程数的文件不会被处理,直接遗漏
核心问题3:错误处理不完整
fopen打开文件失败后仅打印错误,没有终止线程逻辑,后续会传入空指针调用fgets引发段错误。
修复代码示例
首先修改路径拼接逻辑,其次修复线程生命周期管理逻辑,最后补全错误处理:
#include <stdlib.h> #include <dirent.h> #include <pthread.h> #include <string.h> #include <stdio.h> #include <stdint.h> #include "queue.h" void* splitInput(void *arg) { char* filename = (char*)arg; printf("Thread %s Created\n", filename); FILE *file = fopen(filename, "r"); if(file == NULL) { perror("Error opening file"); free(filename); // 释放传入的路径内存 pthread_exit(NULL); } printf("Opened File %s\n", filename); int i = 0; char *cp; char *bp; char line[255]; char *array[5000]; while(fgets(line, sizeof(line), file) != NULL) { bp = line; while(1) { cp = strtok(bp, ",.!? \n"); bp = NULL; if(cp == NULL) { break; } array[i++] = cp; printf("Check print - word %i:%s:\n", i-1, cp); } } fclose(file); free(filename); // 释放传入的路径内存 return 0; } int main(int argc, char *argv[]) { if(argc < 4) { // 新增参数合法性判断 printf("Usage: %s <dir_path> <queue_size> <thread_count>\n", argv[0]); return 1; } DIR* d = opendir(argv[1]); if(d == NULL) { perror("Error opening directory"); return 1; } int queueSize = atoi(argv[2]); int threadCount = atoi(argv[3]); printf("Queue Size: %d\n", queueSize); printf("Thread Count: %d\n", threadCount); pthread_t threads[threadCount]; int i = 0; struct dirent* e; while((e = readdir(d)) != NULL) { if(strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) { continue; } if(i >= threadCount) { // 超过线程数的文件先跳过,可根据需求调整为线程池逻辑处理全部文件 printf("Skip file %s, exceed thread count\n", e->d_name); continue; } printf("entered file %s\n", e->d_name); // 拼接完整路径 int path_len = strlen(argv[1]) + strlen(e->d_name) + 2; char *full_path = malloc(path_len); snprintf(full_path, path_len, "%s/%s", argv[1], e->d_name); pthread_create(&threads[i], NULL, splitInput, full_path); i++; } closedir(d); // 仅join实际创建的线程 for(int j = 0; j < i; j++) { pthread_join(threads[j], NULL); } return 0; }
内容的提问来源于stack exchange,提问作者Shiloh
相关产品推荐
相关产品推荐

