0

im new to multi-thread programming in C. I implemented a thread_create.c file for two thread with a race of chars in linux. But if i wanna do it with a #define n for generical multi-thread file there's some error with pointers

There's the code:

#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;
    
    for(int i=0; i<= pp->times; i++) {
        printf("%c", pp->characters);
        fflush(stdout);
        sleep(1);
    }
    return (void *)&(pp->times);
}


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]);
    }
    
    return 0;
}

And this is the output:

ACEDBAEBDCAEDBEBADBADEADEADEEDDD TA: Times 6 TB: Times 65 TC: Times 4 TD: Times 66 TE: Times 1

Every time, the 2nd and 4th threads points to first char (?) and i cant see the error...

VuciuS
  • 11
  • 1
  • "Every time, the 2nd and 4th threads points to first char" Can you elaborate? What makes you think so? Please show some output you would expect from a correct program. – n. m. could be an AI Apr 10 '23 at 20:36

2 Answers2

0

Your cast to (void **) in the pthread_join call masked the problem.

That is t_returnValue was 32 bit and not 64 bit.

Change:

int *t_returnValue[n];

Into:

void *t_returnValue[n];

And, change your printf into:

printf("T%c: Times %zd\n", (char) first++,
    (ssize_t) *(int *) t_returnValue[j]);

Here is the refactored code:

#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;

    for (int i = 0; i <= pp->times; i++) {
        printf("%c", pp->characters);
        fflush(stdout);
        sleep(1);
    }
    return (void *) &(pp->times);
}

int
main()
{
    pthread_t t[n];

    srand(time(NULL));

    struct print_args t_args[n];
    char first = 'A';

#if 0
    int *t_returnValue[n];
#else
    void *t_returnValue[n];
#endif

    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++) {
#if 0
        pthread_join(t[j], (void **) &t_returnValue[j]);
#else
        pthread_join(t[j], &t_returnValue[j]);
#endif
    }
    first -= n;

#if 1
    printf("\n");
#endif

    for (int j = 0; j < n; j++) {
#if 0
        printf("\n T%c: Times %d", (char) first++, (*t_returnValue)[j]);
#else
        printf("T%c: Times %zd\n", (char) first++,
            (ssize_t) *(int *) t_returnValue[j]);
#endif
    }

    return 0;
}

In the code above, I've used cpp conditionals to denote old vs. new code:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

Note: this can be cleaned up by running the file through unifdef -k


Here is the program output I get now:

AECDBAEDCBAEDCBAEDCBAEDCBEDEDEDEDD
TA: Times 4
TB: Times 4
TC: Times 4
TD: Times 9
TE: Times 8
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
0
   (*t_returnValue)[j]

This is wrong. You need

     *t_returnValue[j]

Live demo.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243