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

C语言多线程:for循环中pthread_join与pthread_create的返回值指针问题

问题分析与修复

核心错误:返回值访问方式错误

你的代码中,t_returnValue是int *t_returnValue[n],即存储int指针的数组。每个线程返回的是&pp->times(也就是&t_args[j].times),所以t_returnValue[j]保存的是对应times变量的地址。

但打印时你写的(*t_returnValue)[j]是错误的:

  • *t_returnValue等价于t_returnValue[0],也就是第一个线程返回的地址
  • (*t_returnValue)[j]相当于访问这个地址指向的内存的第j个int,完全偏离了预期逻辑,会越界读取栈上的随机数据,这就是你看到65、66这类异常值的原因。

正确写法应该是*t_returnValue[j],表示取第j个线程返回地址指向的int值。

潜在问题:返回栈变量地址的风险

当前代码中,线程返回的是main函数栈上t_args[j].times的地址,虽然因为main会调用pthread_join等待所有线程结束后才处理返回值,栈内存暂时有效,但这种写法不安全:如果后续修改代码,比如在pthread_join前释放了t_args或main提前退出,线程返回的地址就会变成无效野指针。

更稳妥的两种方案:

  1. 直接返回值(将int转为void)*:Linux系统中int的大小不超过void*的大小,通过intptr_t做类型转换可以保证安全,直接返回times的值而非地址。
  2. 动态分配内存存储返回值:线程中用malloc分配内存存储times,返回该指针,main读取后记得free避免内存泄漏。

修正后的代码

方案1:直接返回值(推荐,简单高效)

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdint.h> // 用于intptr_t类型
#define n 5

struct print_args {
    int times;
    char characters;
};

void * print_sum(void * parameters) {
    struct print_args * pp = (struct print_args *) parameters;
    
    for(int i=0; i<= pp->times; i++) {
        printf("%c", pp->characters);
        fflush(stdout);
        sleep(1);
    }
    // 用intptr_t做中转,安全转换int到void*
    return (void*)(intptr_t)pp->times;
}


int main() {
    pthread_t t[n];
    srand(time(NULL));

    struct print_args t_args[n];
    char first = 'A';
    
    void *t_returnValue[n]; // 直接存储void*类型返回值
    
    for(int j=0; j<n; j++) {
        t_args[j].times = rand() % 10;
        t_args[j].characters = first;
        first++;
    }
    
    for(int j=0; j<n; j++) {
        pthread_create(&t[j], NULL, &print_sum, &t_args[j]);
    }
    for(int j=0; j<n; j++) {
        pthread_join(t[j], &t_returnValue[j]);
    }
    first -= n;
    for(int j=0; j<n; j++) {
        // 把void*转回int
        printf("\n T%c: Times %d", (char)first++, (int)(intptr_t)t_returnValue[j]);
    }
    
    return 0;
}

方案2:动态分配内存返回值

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#define n 5

struct print_args {
    int times;
    char characters;
};

void * print_sum(void * parameters) {
    struct print_args * pp = (struct print_args *) parameters;
    // 分配内存存储返回值
    int *ret = malloc(sizeof(int));
    *ret = pp->times;
    
    for(int i=0; i<= pp->times; i++) {
        printf("%c", pp->characters);
        fflush(stdout);
        sleep(1);
    }
    return ret;
}


int main() {
    pthread_t t[n];
    srand(time(NULL));

    struct print_args t_args[n];
    char first = 'A';
    
    int *t_returnValue[n];
    
    for(int j=0; j<n; j++) {
        t_args[j].times = rand() % 10;
        t_args[j].characters = first;
        first++;
    }
    
    for(int j=0; j<n; j++) {
        pthread_create(&t[j], NULL, &print_sum, &t_args[j]);
    }
    for(int j=0; j<n; j++) {
        pthread_join(t[j], (void **)&t_returnValue[j]);
    }
    first -= n;
    for(int j=0; j<n; j++) {
        printf("\n T%c: Times %d", (char)first++, *t_returnValue[j]);
        free(t_returnValue[j]); // 释放动态分配的内存
    }
    
    return 0;
}

验证结果

修正后运行程序,会输出每个线程正确的times值,不会再出现随机异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:25:04