简体   繁体   中英

Segmentation fault using threads in C

I'm getting a seg fault within this code, but I can't find the problem anywhere. It compiles just fine with -lpthread, but it just won't run. This program takes in an integer from the command line and then creates a new thread to calculate the collatz conjecture using that value. This is my code:

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

void print_con();
void calc_con(int *n);

int * values[1000];

int main(int argc, char * argv[])
{
        int* num;
        *num = 15;
        pthread_t thread;
        pthread_create(&thread,(pthread_attr_t*)NULL, (void *)&calc_con, (void *)num);
        pthread_join(thread, NULL);
        print_con();
        return 0;

}

void calc_con(int *n)
{
        int i = 0;
        int * x;
        *x = *n;
        *values[0] = *x;
        while(*x > 1)
        {
                if(*x % 2 == 0)
                        *x /= 2;
                else if(*x % 2 == 1)
                {
                        *x *= 3;
                        *x++;
                }
                i++;
                *values[i] = *x;
        }
        pthread_exit(0);
}

void print_con()
{
        int i;
        for(i = 0; i < 1000; i++)
        {
                if(*values[i] > 0)
                        printf("%d", *values[i]);
        }
}

okay you need to pass a void * as an argument to pthread_create , but you still need to respect the basics:

int* num;
*num = 15;
pthread_t thread;
pthread_create(&thread,(pthread_attr_t*)NULL, (void *)&calc_con, (void *)num);

Here *num = 15; you're writing 15 to an uninitialized pointer . That's undefined behaviour .

I would do:

int num = 15;
pthread_t thread;
pthread_create(&thread,(pthread_attr_t*)NULL, &calc_con, &num);

note that you don't have to cast to void * from pointers on non-void. Since num is declared in the main routine, you can pass a pointer on it to your threads safely.

note that as pointed by dasblinkenlight, you also have to fix the recieving end, in calc_con , which has the same issue:

int * x;  // uninitialized pointer
*x = *n;  // copy data "in the woods"

just dereference into a local variable and you have your value:

int x = *((int *)n);

and another one:

int * values[1000];

is an uninitialized array of integer pointers, not an array of integers like you're intending. It should be

int values[1000];

then

values[0] = x;

(it's not because there's a lot of * operators that it's good code)

You are passing an int to your thread using a void* . This will work on many platforms, but there is no guarantees that the number would "round-trip" correctly. Once you get pointer back, you save it in a dereferenced uninitialized pointer, which is incorrect.

Pass a pointer to num instead, and copy the pointer into x directly:

void calc_con(void *n);
...
void calc_con(void *n) {
        int i = 0;
        int * x = n;
        *values[0] = *x;
        while(*x > 1) {
                if(*x % 2 == 0) {
                        *x /= 2;
                } else if(*x % 2 == 1) {
                        *x *= 3;
                        *x++;
                }
                i++;
                *values[i] = *x;
        }
        pthread_exit(0);
}
...
int num = 15;
pthread_create(&thread,(pthread_attr_t*)NULL, calc_con, (void *)&num);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM