1

I am working on a function that creates a thread and calculates the Fibonacci sequence to a certain user inputted value. For example, if a user enters 5, the output will be: 0 1 1 2 3 5

However, the sequence must be calculated in the created thread, and the results have to be printed out after the thread is exited.

I can create the thread and calculate the sequence, but I need to pass the array fibSequence[] back to the original thread using pthread_exit and pthread_join. I am having trouble figuring out the syntax and can't find any examples of people passing arrays through.

What I have so far: I created a function fib_runner() that is called by a newly created thread. The Fibonacci sequence is created and placed into the array fibSequence[]. I need to pass this back through to the main function. I am temporarily printing out the sequence in the function, but it should be printed in the main.

Thank you!

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

void* fib_runner(void* arg)
{
    int *limit_ptr = (int*) arg;
    int limit = *limit_ptr;
    int fibSequence[limit];

    int size = sizeof(fibSequence)/sizeof(fibSequence[0]);
    printf("Size: %d\n", size);

    fibSequence[0] = 0;
    fibSequence[1] = 1;

    for (int i = 2; i <= size; i++)
    {
        fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
    }

    for (int i = 0; i <= size; i++)
    {
        printf("%d ", fibSequence[i]);
    }
    pthread_exit(0);
}

int main(int argc, char **argv)
{
    int limit;
    printf("Enter Number: ");
    scanf("%d", &limit);

    pthread_t tid;
    pthread_attr_t attr;
    pthread_attr_init(&attr);

    pthread_create(&tid, &attr, fib_runner, &limit);
    pthread_join(tid, NULL);
}
sg7
  • 6,108
  • 2
  • 32
  • 40
  • Possible duplicate of [Returning an array using C](https://stackoverflow.com/questions/11656532/returning-an-array-using-c) – jww Apr 01 '18 at 23:55

3 Answers3

0

Currently, the array is a local variable, so it would go out of scope when the function exits. You need to dynamically allocate memory for it instead:

int *fibSequence = malloc(sizeof(int) * limit);

Then return this pointer from the function:

return fibSequence;

In your main function, you then pass the address of a pointer to receive this value. Then you can print the content of the array. When you're done, be sure to free it:

int *fibSequence;
pthread_join(tid, (void **)&fibSequence);

for (int i = 0; i < limit; i++)
{
    printf("%d ", fibSequence[i]);
}
free(fibSequence);

Also, you don't need size in your thread function, since it is the same as limit, and the way you currently calculate it won't work anyway since you now have a pointer instead of an array. Your loop limit in fib_runner also goes one past the end of the array. The exit condition should be i < size, not i <= size.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • When I use return, doesn't that make pthread_exit unreachable? Also, when I initialize *fibSequence with malloc, should I do that before or after I initialize its size with limit? – Namit Patel Apr 02 '18 at 00:10
  • @NamitPatel Returning from a thread function is the same as calling `pthread_exit`. They are interchangeable. For `fibSequence`, the line above that calls `malloc` is all you need (plus error checking to ensure `malloc` was successful). – dbush Apr 02 '18 at 00:17
  • Ok, I removed pthread_exit, I didn't know return was the same. Also, when I call malloc, I don't think it is initializing the correct number of elements. For example, when I enter 5 as the input, it prints 0 1 0 0 0 – Namit Patel Apr 02 '18 at 00:23
  • Never mind it was an error on my end. Used size instead of limit in my for loop so it was ending early. Thanks for the help! Program works! – Namit Patel Apr 02 '18 at 00:27
0

All the threads running within a process share the same address space, file descriptors, stack and other process related attributes.

Threads are sharing memory by definition, they do not own anything except stack and local variables;

If you make fibSequence[limit] global then all threads will have access to it.

You can also declare fibSequence[limit] on the stack in main and pass pointer to it to your thread.

To pass multiple arguments it is convenient to wrap them up in a structure. The solutions below employ:

struct arg_struct {
    int limit;
    int *ptrFib;
}args;

Program:

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

struct arg_struct {
    int limit;
    int *ptrFib;
}args;

void* fib_runner(void* arg)
{
    struct arg_struct *a = (struct arg_struct *) arg;
    int size = a->limit;
    int * fibSequence = a->ptrFib;  

    fibSequence[0] = 0;
    fibSequence[1] = 1;

    for (int i = 2; i <= size; i++){
        fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
    }    
    pthread_exit(0);
}

int main(int argc, char **argv)
{
    int limit;
    printf("Enter Number: ");
    scanf("%d", &limit);
    int fibSequence[limit];

    struct arg_struct argF;
    argF.limit = limit;
    argF.ptrFib = fibSequence;

    pthread_t tid;
    pthread_attr_t attr;
    pthread_attr_init(&attr);

    pthread_create(&tid, &attr, fib_runner, &argF);
    pthread_join(tid, NULL);

    for (int i = 0; i <= limit; i++){
        printf("%d ", fibSequence[i]);
    }
}

Output:

Enter Number: 5                                                                                                                                                                                                                                                               
0 1 1 2 3 5 

The solution with global variable argF is of course possible but it is less elegant.

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

struct arg_struct {
    int limit;
    int *ptrFib;
}args;

struct arg_struct argF;

void* fib_runner()
{
    int size = argF.limit;
    int * fibSequence = argF.ptrFib;

    fibSequence[0] = 0;
    fibSequence[1] = 1;

    for (int i = 2; i <= size; i++){
        fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
    }
    pthread_exit(0);
}

int main(int argc, char **argv)
{
    int limit;
    printf("Enter Number: ");
    scanf("%d", &limit);
    int fibSequence[limit];

    argF.limit = limit;
    argF.ptrFib = fibSequence;

    pthread_t tid;
    pthread_attr_t attr;
    pthread_attr_init(&attr);

    pthread_create(&tid, &attr, fib_runner, NULL);
    pthread_join(tid, NULL);

    for (int i = 0; i <= limit; i++){
        printf("%d ", fibSequence[i]);
    }
}
sg7
  • 6,108
  • 2
  • 32
  • 40
  • Variable length arrays are not allowed at file scope, and returning a pointer to an array declared locally invokes undefined behavior since it goes out of scope. – dbush Apr 02 '18 at 00:01
  • The trouble I'm having with this solution is that I don't get the value for limit until the main function. So I don't know how I could initialize it as a global variable when I don't have limit until the user enters it. Unless there's a way to do it that I'm not thinking about. EDIT: What dbush said. – Namit Patel Apr 02 '18 at 00:02
  • @dbush Thank you for your comment! I did not made myself clear. What I meant was to declare `fibSequence[limit]` in the `main`. The life span of such array is equal to the life of the program. – sg7 Apr 02 '18 at 00:05
  • @NamitPatel This sequence will work in C99: `scanf("%d", &limit); int fibSequence[limit];` or use `dbush` dynamic approach. – sg7 Apr 02 '18 at 00:11
0

you have to pass in a value of void * to pthread_exit which is pthread_exit(( void * ) &fibSequence, once that function is called the passed in value will populate the second argument to pthread_join, the second argument will be a pointer to a pointer void ** it will hold the values passed in to pthred_exit

0.sh
  • 2,659
  • 16
  • 37