【问题标题】:How to pass value to a Grandchild thread under a Child thread from Parent thread or Child thread in C++如何从 C++ 中的父线程或子线程将值传递给子线程下的孙子线程
【发布时间】:2021-12-17 06:54:50
【问题描述】:

我有一个包含以下值的 file.txt: 1234 567 8910

我想用 C++ 创建一个程序,它创建 x 个子线程,其中 x 是“file.txt”中的行数。子线程接收到该行,因此它将该行拆分为数字并将它们存储在一个数组中。

然后我想在每个子线程下创建 y 个孙线程,其中 y 是该子线程数组中的位数或接收到的行值,并将每个孙线程传递一个数字。

例如,对于上面的file.txt,我在main()中的父线程会创建3个子线程。第一个子线程将收到“1234”,第二个“567”,第三个“8910”。 然后第一个孩子将创建 4 个孙线程并传递第一个孙线程“1”,第二个“2”,第三个“3”,第四个“4”。 同样,第二个子线程将创建 3 个孙线程并传递“5”、“6”、“7”位。 最后,第三个子线程将创建 4 个孙线程并传递“8”、“9”、“1”、“0” 数字。

我想使用多线程并行传递所有这些值。在子线程之前,我能够让一切正常工作,并且我能够创建适量的孙线程,但我无法将值传递给它们。非常感谢任何帮助和指导。

这是我的代码:(请指导我修复它)

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

struct info {
    int* digit = new int;
    int* totalDigits = new int;
};

struct grandchildThreadData {
    int GCTDdigit;
    int GCTDgrandchildIndex;
    int GCTDchildIndex;
    info* GCTDinfo = new info;
    info* GCTDparentInfo = new info;
};

struct childThreadData {
    long int CTDlineValue;
    int CTDchildIndex;
    info* CTDinfo = new info;
};

// thread declaration
void* childThread(void*);
void* grandchildThread(void*);

// function to convert and store line to digits
int* digitSeparator(long int);

// MAIN PROGRAM
int main() {
    // FILE OPENING
    int totalLines{0};
    ifstream file1("file.txt"), file2("file.txt");
    string temp;
    while (getline(file1, temp)) {
        totalLines++;
    }
    file1.close();
    long int* valueOnLine = new long int[totalLines];
    int i =0;
    while (!file2.eof()) {
        file2 >> valueOnLine[i];
        i++;
    }
    file2.close();
    // FILE CLOSING

    // THREAD START

    static struct info* mainInfo = new info[totalLines];
    pthread_t* child = new pthread_t[totalLines];
    // will be used to pass values to child
    static struct childThreadData* Carg = new childThreadData[totalLines];

    // Creating Childthreads
    for (int i = 0; i < totalLines; i++) {
        Carg[i].CTDinfo[i] = mainInfo[i];
        Carg[i].CTDchildIndex = i;
        Carg[i].CTDlineValue = valueOnLine[i];

        if (pthread_create(&child[i], nullptr, childThread, &Carg[i])) {
            fprintf(stderr, "Error creating thread\n");
            return 1;
        }
    }

    // Joining Childthreads
    for (int i = 0; i < totalLines; i++) {
        if (pthread_join(child[i], nullptr)) {
            fprintf(stderr, "Error joining thread\n");
            return 2;
        }
    }

    delete[] valueOnLine;
    delete[] child;
    delete[] Carg;

    return 0;
}

void* childThread(void* i) {
    struct childThreadData* CTptr = (struct childThreadData*)i;

    int totalDigits = log10((float)CTptr->CTDlineValue) + 1;
    int* numberArray = digitSeparator(CTptr->CTDlineValue);
 
    // THIS LINE WILL PUT TOTAL DIGITS INTO mainInfo
    CTptr->CTDinfo[CTptr->CTDchildIndex].totalDigits[0] = totalDigits;

    static struct info* childInfo = new info[totalDigits];  // This can be used to print modified info in grandchild
    pthread_t* grandchild = new pthread_t[totalDigits];
    static struct grandchildThreadData* GCarg = new grandchildThreadData[totalDigits];

    // THIS LINE WILL PUT EACH DIGIT ON CORRECT LOCATION of mainInfo
    for (int i=0; i< totalDigits; i++) {
        CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i] = numberArray[i];
    }

    // GRANDCHILD THREAD
    for (int i = 0; i < totalDigits; i++) {
        GCarg[i].GCTDinfo[i] = childInfo[i];    // grandchild to child communication but does not work
        // or
        GCarg[i].GCTDparentInfo[i] = CTptr->CTDinfo[i]; // grandchild to parent communication but does not work
        GCarg[i].GCTDgrandchildIndex = CTptr->CTDchildIndex;    // Here CTptr->CTDchildIndex should pass 0, 1, 2 to grandchild but I get different values
        GCarg[i].GCTDchildIndex = i; // This line works fine for some reason
        GCarg[i].GCTDdigit = CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i]; // This line should pass the correct digit, but again, I am getting different results in grandchild
     
        if (pthread_create(&grandchild[i], nullptr, grandchildThread, &GCarg[i])) {
            fprintf(stderr, "Error creating thread\n");
        }
    }

    //Joining GrandChildthreads
    for (int i = 0; i < totalDigits; i++) {
        if (pthread_join(grandchild[i], nullptr)) {
            fprintf(stderr, "Error joining thread\n");
        }
    }

    return nullptr;
}

void* grandchildThread(void* i) {
    struct grandchildThreadData* GCTptr = (struct grandchildThreadData*)i;

    // THIS LINE SHOULD PRINT THE DIGIT
    cout << GCTptr->GCTDdigit;

    return nullptr;
}

int* digitSeparator(long int number) {
    int 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;
}

【问题讨论】:

  • 我可以假设这是课程的作业要求吗?如果不是这样,那么您的事情就会变得过于复杂,因为这可能会导致性能损失。
  • 您没有使用std::thread的任何特殊原因?
  • 在我看来,这完全是一种毫无意义的线程应用。
  • 是的@user4581301,这是一个分配要求。
  • 那么,您正在学习 C++,但您需要使用特定于平台的 C API 吗?这听起来很糟糕:-(

标签: c++ multithreading grandchild


【解决方案1】:

这不是程序中问题的详尽列表,但它解决了一些基本问题。

  • 您的程序不会检查file.txt 是否成功打开。如果不是,程序将继续运行,直到出现有符号整数溢出 - 这意味着程序有未定义的行为

  • 如果文件成功打开,你会遇到heap-buffer-overflow

    // Creating Childthreads
    for(int i = 0; i < totalLines; i++) {
         Carg[i].CTDinfo[i] = mainInfo[i];        // <- here
    

    这是因为CTDinfo[i]i &gt; 0 时超出范围。 CTDinfo 是指向单个 info 的指针 - 而不是 infos 中的 totalLines

  • 下面也一样。 CTDinfo 不能被视为一个数组,因为它是指向单个 info 的指针 - 而 digit 是指向单个 int 的指针 - 不是 int 的数组。

    // THIS LINE WILL PUT EACH DIGIT ON CORRECT LOCATION of mainInfo
    for(int i = 0; i < totalDigits; i++) {
         CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i] = numberArray[i];
    }
    

建议:

  • 编写一个小得多的程序来掌握线程的窍门。
  • 编写一个小得多的程序来学习如何构建非常复杂的结构(如果您确实需要这样做)。使用 C++ 类,例如 std::vector。如果您将所有手动内存管理替换为标准 C++ 容器,我怀疑该程序是否需要单个 new/new[]info 之类的东西看起来像是误会了。没有理由在这里使用指针:
    struct info {
         int* digit = new int;
         int* totalDigits = new int;
    };
    
  • 使用std::thread 及其支持函数和类,而不是pthread 中特定于平台的C API。

【讨论】:

    【解决方案2】:

    问题是由使用静态结构引起的:

    所以,如果我们替换:

    static struct childThreadData* Carg = new childThreadData[totalLines];
    static struct grandchildThreadData* GCarg = new grandchildThreadData[totalLines];
    

    与:

    childThreadData* Carg = new childThreadData[totalLines];
    grandchildThreadData* GCarg = new grandchildThreadData[totalLines];
    

    它会正常工作的。

    【讨论】:

    • 不,这还远远不够。有太多越界访问和其他错误,我什至无法最终确定写出正确的答案。
    猜你喜欢
    • 2020-02-21
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    相关资源
    最近更新 更多