首页 > 解决方案 > Why cant I cast a void* back to an int* and dereference it?

问题描述

Im trying to understand threading in C from a lab from my teacher and this is the way he had us do it in class.

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

#define numberlen 1000000
int sum = 0;
int arr[numberlen];


void* Summing(void* param)
{
    int n = *((int*)param); //I'm guessing this is where my issue is but I'm still a first year so i'm not sure.
    int base = 500000 * n;
    for(int i =0; i<500000;i++)
    {
        sum += arr[i+base];
    }
}




int main()
{
    int nonthreadsum = 0;
    pthread_t thread_id_first;
    pthread_t thread_id_second;
    


    srand(time(NULL)); 
    
    for(int i = 0; i<numberlen;i++)
    {
        int r = (rand() % 10);
        arr[i] = r;
        nonthreadsum += r;
    }
    printf("%d\n",nonthreadsum);

    pthread_create(&thread_id_first, NULL, Summing, (void*)0);
    pthread_create(&thread_id_second, NULL, Summing, (void*)1);

    
    printf("%d\n", sum);


    return 1;
}

The issue I keep running into is that pthread functions only allow void*'s as arguments to pass to the actual function to be run. Otherwise I'd just put 0 or 1 in as the argument. If anyone knows a way around this i'd appreciate it.

标签: cmultithreadingpthreads

解决方案


It's allowed (in some cases) to cast from an integer to a pointer and from a pointer to an integer. The problem is that's not what you're attempting to do.

When you call pthread_create, you're casting the integer values 1 and 0 to type void *. This is fine. But then in the thread function you do this:

int n = *((int*)param); 

You cast the void * argument to int * and then attempt to dereference that pointer. But you didn't pass in an int *. You passed an int. So your program is treating the values 1 and 0 as pointers (the latter of which is actually a NULL pointer).

Since you converted from int to void * when you passed the values to the function, you want to cast back to int inside of the function.

int n = (int)param; 

That being said, the best way to handle this would be to pass an actual int * to the function and convert it back in the function. Converting from an int * to a void * and back is well defined in all cases.

You can do this by defining variables in the main function to dynamically create memory to hold these values:

int *t1_val = malloc(sizeof(*t1_val));
int *t2_val = malloc(sizeof(*t2_val));
*t1_val = 0;
*t2_val = 1;
pthread_create(&thread_id_first, NULL, Summing, t1_val);
pthread_create(&thread_id_second, NULL, Summing, t2_val);

Then using them in the thread as you were, adding a call to free:

int n = *((int*)param);
free(param);

You could also do this without dynamic allocation by using variables of type int and passing their address, but you would need to make sure those variables don't go out of scope by the time the thread attempts to dereference the pointer.


推荐阅读