อาร์กิวเมนต์หลายรายการในฟังก์ชันที่เรียกโดย pthread_create ()?


96

ฉันต้องการส่งผ่านอาร์กิวเมนต์หลายรายการไปยังฟังก์ชันที่ฉันต้องการเรียกใช้ในเธรดแยกต่างหาก ฉันได้อ่านมาว่าวิธีการทั่วไปในการทำเช่นนี้คือการกำหนดโครงสร้างส่งผ่านฟังก์ชันตัวชี้ไปยังสิ่งนั้นและหักล้างค่าสำหรับอาร์กิวเมนต์ อย่างไรก็ตามฉันไม่สามารถใช้งานได้:

#include <stdio.h>
#include <pthread.h>

struct arg_struct {
    int arg1;
    int arg2;
};

void *print_the_arguments(void *arguments)
{
    struct arg_struct *args = (struct arg_struct *)args;
    printf("%d\n", args -> arg1);
    printf("%d\n", args -> arg2);
    pthread_exit(NULL);
    return NULL;
}

int main()
{
    pthread_t some_thread;
    struct arg_struct args;
    args.arg1 = 5;
    args.arg2 = 7;

    if (pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0) {
        printf("Uh-oh!\n");
        return -1;
    }

    return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}

ผลลัพธ์สำหรับสิ่งนี้ควรเป็น:

5
7

แต่เมื่อฉันเรียกใช้ฉันจะได้รับ:

141921115
-1947974263

ใครรู้ว่าฉันทำผิด?


2
ลองจัดสรรบนฮีปไหม
Carson Myers

1
@ คาร์สันทำไมถึงต้องสร้างความแตกต่าง?
sigjuice

5
โครงสร้างของคุณควรอยู่อย่างน้อยที่สุดตราบเท่าที่ด้ายของคุณ หากคุณกำลังสร้างเธรดและกลับมาจากฟังก์ชันที่เรียกว่า pthread_create () โครงสร้างที่จัดสรรบนสแต็กอาจถูกข้อมูลอื่นเขียนทับและอาจทำให้เกิดปัญหาในฟังก์ชันเธรดของคุณ ในตัวอย่างนี้ไม่ใช่ปัญหาเนื่องจากเธรดการสร้างจะรอให้เธรดของผู้ปฏิบัติงานเสร็จสิ้นก่อนที่จะส่งคืน
Commodore Jaeger

@ Commodore Jaeger อ้อ! ขอบคุณนั่นคือปัญหาที่ฉันพบกับปัญหาอื่น ๆ ที่ฉันกำลังทำงานอยู่ ฉันแก้ไขโดยการจัดสรรบนฮีปโดยใช้ malloc () ตามที่คาร์สันกล่าว นั่นเข้าท่ากว่าตอนนี้
Michael

คำตอบ:


78

เพราะคุณพูด

struct arg_struct *args = (struct arg_struct *)args;

แทน

struct arg_struct *args = arguments;


5
@sigjuice มันไม่ได้ผลสำหรับฉัน ฉันเห็นข้อผิดพลาดในการคอมไพล์: การแปลงไม่ถูกต้องจาก 'void *' เป็น 'arg_struct *'
Neshta


4

main()มีเธรดและตัวแปรสแต็กของตัวเอง จัดสรรหน่วยความจำสำหรับ 'args' ในฮีปหรือทำให้เป็นโกลบอล:

struct arg_struct {
    int arg1;
    int arg2;
}args;

//declares args as global out of main()

จากนั้นแน่นอนเปลี่ยนการอ้างอิงจากargs->arg1เป็นargs.arg1ฯลฯ ..


2

ใช้:

struct arg_struct *args = malloc(sizeof(struct arg_struct));

และส่งผ่านข้อโต้แย้งเช่นนี้:

pthread_create(&tr, NULL, print_the_arguments, (void *)args);

อย่าลืม args ฟรี! ;)



1
struct arg_struct *args = (struct arg_struct *)args;

-> การกำหนดนี้ไม่ถูกต้องฉันหมายถึงควรใช้อาร์กิวเมนต์ตัวแปรในบริบทนี้ ไชโย !!!


1

ในการสร้างเธรดของรหัสนี้จะมีการส่งที่อยู่ของตัวชี้ฟังก์ชัน ต้นตำรับ pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

ควรอ่านเป็น pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

วิธีที่ดีในการจำคืออาร์กิวเมนต์ทั้งหมดของฟังก์ชันนี้ควรเป็นที่อยู่

some_thread มีการประกาศแบบคงที่ดังนั้นที่อยู่จึงถูกส่งอย่างถูกต้องโดยใช้ &มีการประกาศแบบคงที่เพื่อให้อยู่จะถูกส่งอย่างถูกต้องโดยใช้

ฉันจะสร้างpthread_attr_tตัวแปรจากนั้นใช้pthread_attr_init()มันและส่งที่อยู่ของตัวแปรนั้น แต่การส่งผ่านNULLตัวชี้ก็ใช้ได้เช่นกัน

&ด้านหน้าของป้ายชื่อฟังก์ชั่นเป็นสิ่งที่เป็นสาเหตุของปัญหาที่นี่ ป้ายกำกับที่ใช้เป็นvoid*ฟังก์ชันอยู่แล้วดังนั้นจึงจำเป็นต้องใช้ป้ายกำกับเท่านั้น

การพูด!= 0ด้วยการโต้แย้งครั้งสุดท้ายดูเหมือนจะทำให้เกิดพฤติกรรมที่ไม่แน่นอน การเพิ่มสิ่งนี้หมายความว่ามีการส่งผ่านบูลีนแทนการอ้างอิง

คำตอบของ Akash Agrawal ก็เป็นส่วนหนึ่งของการแก้ปัญหาของรหัสนี้เช่นกัน


1

ฉันมีคำถามเดียวกับไมเคิลโปสเตอร์ต้นฉบับ

อย่างไรก็ตามฉันได้พยายามใช้คำตอบที่ส่งมาสำหรับรหัสเดิม แต่ไม่ประสบความสำเร็จ

หลังจากลองผิดลองถูกนี่คือรหัสเวอร์ชันของฉันที่ใช้งานได้ (หรืออย่างน้อยก็ใช้ได้กับฉัน!) และหากคุณมองอย่างใกล้ชิดคุณจะสังเกตได้ว่ามันแตกต่างจากโซลูชันก่อนหน้านี้ที่โพสต์ไว้

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

struct arg_struct
{
   int arg1;
   int arg2;
} *args;

void *print_the_arguments(void *arguments)
{
   struct arg_struct *args = arguments;
   printf("Thread\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   pthread_exit(NULL);
   return NULL;
}

int main()
{
   pthread_t some_thread;
   args = malloc(sizeof(struct arg_struct) * 1);

   args->arg1 = 5;
   args->arg2 = 7;

   printf("Before\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   printf("\n");


   if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
   {
      printf("Uh-oh!\n");
      return -1;
   }

   return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.