使用pthread_create时参数错误求助:多线程子串统计程序问题
解决pthread_create参数错误及多线程子串统计问题
我来帮你搞定pthread_create参数使用的问题!先从这个函数的核心要求说起,再结合你的代码一步步修正,顺便优化多线程统计的逻辑(避免全局变量竞态问题)。
首先,明确pthread_create的正确用法
pthread_create的函数原型是:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
常见的参数错误主要集中在线程函数签名和参数传递上:
- 线程函数必须是
void* (*)(void*)类型:也就是接受一个void*参数,返回void*,你的void occurrence()完全不符合这个要求,这是最可能的错误原因。 - 参数传递要避免直接用全局变量:多线程同时操作全局变量会引发竞态条件,统计结果会出错,最好把每个线程需要的数据封装成结构体单独传递。
修正后的完整代码示例
结合你的需求,我调整了代码结构,解决参数问题同时优化多线程逻辑:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <errno.h> #define NUM_THREADS 4 #define MAX 1024 // 封装每个线程需要的参数,避免全局变量竞态 typedef struct { char *main_str; // 主字符串s1 char *sub_str; // 子串s2 int start_pos; // 线程处理的起始索引 int end_pos; // 线程处理的结束索引 int match_count; // 该线程统计的匹配数 } ThreadTask; // 修正后的线程函数,符合pthread要求的签名 void* count_occurrences(void *arg) { ThreadTask *task = (ThreadTask*)arg; int main_len = strlen(task->main_str); int sub_len = strlen(task->sub_str); task->match_count = 0; // 如果子串比主串长,直接返回0 if (sub_len > main_len || sub_len == 0) { pthread_exit(NULL); } // 遍历分配给当前线程的区间,统计子串 for (int i = task->start_pos; i <= task->end_pos - sub_len + 1; i++) { if (strncmp(&task->main_str[i], task->sub_str, sub_len) == 0) { task->match_count++; } } return (void*)&task->match_count; } // 读取文件中的两个字符串 int read_strings(char **s1, char **s2) { FILE *fp = fopen("strings.txt", "r"); if (fp == NULL) { perror("ERROR: can't open strings.txt"); return 0; } *s1 = (char*)malloc(MAX * sizeof(char)); *s2 = (char*)malloc(MAX * sizeof(char)); if (*s1 == NULL || *s2 == NULL) { perror("ERROR: malloc failed"); fclose(fp); return 0; } // 读取两行字符串(假设文件第一行是s1,第二行是s2) if (fgets(*s1, MAX, fp) == NULL || fgets(*s2, MAX, fp) == NULL) { perror("ERROR: failed to read strings from file"); free(*s1); free(*s2); fclose(fp); return 0; } // 去掉字符串末尾的换行符 (*s1)[strcspn(*s1, "\n")] = '\0'; (*s2)[strcspn(*s2, "\n")] = '\0'; fclose(fp); return 1; } int main() { char *s1, *s2; if (!read_strings(&s1, &s2)) { exit(EXIT_FAILURE); } int main_len = strlen(s1); int sub_len = strlen(s2); pthread_t threads[NUM_THREADS]; ThreadTask thread_tasks[NUM_THREADS]; int total_matches = 0; // 给每个线程分配处理区间 int chunk_size = main_len / NUM_THREADS; for (int i = 0; i < NUM_THREADS; i++) { thread_tasks[i].main_str = s1; thread_tasks[i].sub_str = s2; thread_tasks[i].start_pos = i * chunk_size; // 最后一个线程处理剩余的所有字符,避免遗漏 if (i == NUM_THREADS - 1) { thread_tasks[i].end_pos = main_len - 1; } else { thread_tasks[i].end_pos = (i + 1) * chunk_size - 1; } thread_tasks[i].match_count = 0; // 正确调用pthread_create:传递线程ID、默认属性、线程函数、任务结构体 int ret = pthread_create(&threads[i], NULL, count_occurrences, (void*)&thread_tasks[i]); if (ret != 0) { fprintf(stderr, "ERROR: pthread_create failed for thread %d: %s\n", i, strerror(ret)); exit(EXIT_FAILURE); } } // 等待所有线程完成,汇总统计结果 for (int i = 0; i < NUM_THREADS; i++) { int *thread_count; pthread_join(threads[i], (void**)&thread_count); total_matches += *thread_count; } printf("Total occurrences of substring in main string: %d\n", total_matches); // 释放内存 free(s1); free(s2); return 0; }
关键修正点说明
- 线程函数签名修正:把原来的
void occurrence()改成void* count_occurrences(void *arg),完全符合pthread的要求。 - 参数传递优化:用
ThreadTask结构体封装每个线程的独立数据,避免多个线程同时操作全局变量导致的竞态问题。 - 正确调用pthread_create:第四个参数传递结构体的地址(转成
void*),让线程能拿到自己的任务数据。 - 添加pthread_join:主线程等待所有子线程执行完毕后再汇总结果,避免子线程还没统计完主线程就退出。
- 文件读取完善:补充了内存分配失败、读取失败的错误处理,同时去掉了字符串末尾的换行符,避免统计出错。
内容的提问来源于stack exchange,提问作者brian nyaberi
相关产品推荐
相关产品推荐

