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

C++多线程场景下如何从父线程或子线程向孙线程传递数值

问题修复说明

核心错误点

  • 子线程中childInfo、GCarg使用static修饰,属于全局共享变量,多个子线程并行执行时会互相覆盖数据,导致传参混乱
  • info结构体中的digit、totalDigits仅分配了1个int的内存,后续作为数组存储多位数时直接越界访问,引发未定义行为
  • 多处数组索引逻辑错误,对指针类型的结构体成员访问时索引逻辑完全混乱
  • 文件读取使用eof()判断终止条件,会多读一行无效数据
  • 存在大量内存泄漏,动态分配的内存未正确释放

修复后完整代码

#include <iostream>
#include <pthread.h>
#include <math.h>
#include <fstream>
#include <cstdlib>
#include <unistd.h>
using namespace std;

// 简化结构体,去掉不必要的指针避免越界
struct grandchildThreadData {
    int GCTDdigit;
    int GCTDchildIndex; // 所属子线程序号
    int GCTDgrandchildIndex; // 孙线程自身序号
};

struct childThreadData {
    long int CTDlineValue;
    int CTDchildIndex;
};

// 线程函数声明
void* childThread(void*);
void* grandchildThread(void*);

// 数值拆分为单个数字的函数
int* digitSeparator(long int, int&);

int main() {
    // 读取文件统计行数,同时读取内容
    int totalLines{0};
    ifstream file("file.txt");
    string temp;
    // 先统计行数
    while (getline(file, temp)) {
        if (!temp.empty()) totalLines++; // 跳过空行
    }
    file.clear();
    file.seekg(0); // 重置文件指针到开头
    long int* valueOnLine = new long int[totalLines];
    for (int i = 0; i < totalLines; i++) {
        file >> valueOnLine[i];
    }
    file.close();

    pthread_t* child = new pthread_t[totalLines];
    childThreadData* Carg = new childThreadData[totalLines];

    // 创建子线程
    for (int i = 0; i < totalLines; i++) {
        Carg[i].CTDchildIndex = i;
        Carg[i].CTDlineValue = valueOnLine[i];
        if (pthread_create(&child[i], nullptr, childThread, &Carg[i])) {
            fprintf(stderr, "Error creating child thread\n");
            return 1;
        }
    }

    // 等待所有子线程结束
    for (int i = 0; i < totalLines; i++) {
        if (pthread_join(child[i], nullptr)) {
            fprintf(stderr, "Error joining child thread\n");
            return 2;
        }
    }

    // 释放内存
    delete[] valueOnLine;
    delete[] child;
    delete[] Carg;
    return 0;
}

void* childThread(void* arg) {
    childThreadData* CTptr = (childThreadData*)arg;
    int totalDigits = 0;
    int* numberArray = digitSeparator(CTptr->CTDlineValue, totalDigits);

    pthread_t* grandchild = new pthread_t[totalDigits];
    grandchildThreadData* GCarg = new grandchildThreadData[totalDigits]; // 去掉static,每个子线程有独立的参数数组

    // 创建孙线程
    for (int i = 0; i < totalDigits; i++) {
        GCarg[i].GCTDchildIndex = CTptr->CTDchildIndex;
        GCarg[i].GCTDgrandchildIndex = i;
        GCarg[i].GCTDdigit = numberArray[i];
        if (pthread_create(&grandchild[i], nullptr, grandchildThread, &GCarg[i])) {
            fprintf(stderr, "Error creating grandchild thread\n");
        }
    }

    // 等待所有孙线程结束
    for (int i = 0; i < totalDigits; i++) {
        pthread_join(grandchild[i], nullptr);
    }

    // 释放内存
    delete[] numberArray;
    delete[] grandchild;
    delete[] GCarg;
    return nullptr;
}

void* grandchildThread(void* arg) {
    grandchildThreadData* GCTptr = (grandchildThreadData*)arg;
    // 注:cout不是线程安全的,多线程同时输出可能出现乱序,属于正常现象
    cout << "子线程" << GCTptr->GCTDchildIndex << " 孙线程" << GCTptr->GCTDgrandchildIndex << " 收到数字:" << GCTptr->GCTDdigit << endl;
    return nullptr;
}

int* digitSeparator(long int number, int& totalDigits) {
    totalDigits = log10((float)number) + 1;
    int* separatorPtr = new int[totalDigits];
    int j = 0;
    for (int i = totalDigits - 1; i >= 0; i--) {
        long int divisor = pow((float)10, i);
        long int digit = number / divisor;
        number -= digit * divisor;
        separatorPtr[j] = digit;
        j++;
    }
    return separatorPtr;
}

测试说明

针对示例file.txt:

1234
567
8910

运行后会输出11条结果(4+3+4),包含所有拆分后的数字,线程调度顺序不同输出顺序会有差异,所有数字传递均正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:57:03