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

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

关键修正点说明

  1. 线程函数签名修正:把原来的void occurrence()改成void* count_occurrences(void *arg),完全符合pthread的要求。
  2. 参数传递优化:用ThreadTask结构体封装每个线程的独立数据,避免多个线程同时操作全局变量导致的竞态问题。
  3. 正确调用pthread_create:第四个参数传递结构体的地址(转成void*),让线程能拿到自己的任务数据。
  4. 添加pthread_join:主线程等待所有子线程执行完毕后再汇总结果,避免子线程还没统计完主线程就退出。
  5. 文件读取完善:补充了内存分配失败、读取失败的错误处理,同时去掉了字符串末尾的换行符,避免统计出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:32:51