Cast to Pointer from Integer of Different Size, Pthread Code

Cast to Pointer from Integer of Different Size, Pthread Code

I have this code for matrix multiplication, using pthreads, but I get the error "cast to pointer from integer of different size"

I don't know what is wrong.I am new to pthread, and this is what I have made so far:

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

#define NTHREADS 4

int dim ;
pthread_mutex_t m;       /* Mutex protecting the sum value */
pthread_t thread_id[NTHREADS];  /* Thread ids */
float **A, **B, **C;

void *prod (void *s){
    int *id=(int *)s;
    int idd=*id;


    /* Define local variables */
    int i,j,k, start, end, len ;
    float **Aa, **Bb, **Cc;

    start = dim*idd;       /* Start of this threads slice of the vectors */
    end   = start + dim;      /* End of the slice */


    for (i = 0 ; i < dim; i++)
    {
        for (j = 0;  j < dim; j++)
        {
            Cc[i][j] = 0;
            for (i=start; i<end ; i++) {

                Cc[i][j] += Aa[i][k] * Bb[k][j];
            }
        }
    }
    pthread_mutex_lock (&m);     /* Lock the mutex */
    C[i][j] += Cc[i][j];                /* Update the shared variable */
    pthread_mutex_unlock (&m);   /* Unlock the mutex */

    pthread_exit(NULL);            /* Done! */
}

int main ( int argc, char *argv[] )
{
    void *status;
    float **A, **B, **C;
    int i,j,k;

    if ( argc == 2)
        dim = atoi(argv[1]); // get the dimension of the matrix
    // from the command prompt

    else
        dim = 128;



    A = (float **)malloc(sizeof(float*)*dim);
    B = (float **)malloc(sizeof(float*)*dim);
    C = (float **)malloc(sizeof(float*)*dim);

    for (i = 0 ; i < dim; i++)
    {
        A[i] = (float *)malloc(sizeof(float)*dim);
        B[i] = (float *)malloc(sizeof(float)*dim);
        C[i] = (float *)malloc(sizeof(float)*dim);
    }

    for (i=0; i<dim; i++)
    {
        for (j = 0 ; j < dim; j++)
        {
            A[i][j]=rand();
            B[i][j]=rand();
        }
    }

    struct timeval t1, t2;
    gettimeofday(&t1, NULL);

    // you need to parallelize this
    // perform the multiplication
    for(i=0;i<NTHREADS;i++) {

        pthread_create(&thread_id[i], NULL, prod, (void *)i);
    }
    /* Wait on the other threads */
    for(i=0;i<NTHREADS;i++) {
        pthread_join(thread_id[i], &status);
    }

    gettimeofday(&t2, NULL);

    double t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec ) / 1000000.0;
    // take the difference and report it in seconds
    printf("execution time %f seconds\n",t);
}

the error at this line:

pthread_create(&thread_id[i], NULL, prod, (void *)i); 
15

3 Answers

You are wrongly using an hack to pass an integer to a thread. The idea behind what you are doing is an integer is 4 bytes and a pointer is 4 bytes in x86_32 (8 bytes in x86_64) so I can convert an integer type to a pointer type and then convert it back to an int type without losing any data. This works in the majority of the scenarios, but there is not guarantee that a pointer and an integer have the same size. The C standard does not specify this.

The compiler returns a warning because you are converting an int to void * which may have different size, ( but in fact in your machine they have the same size).

There is a error in you code, when you convert the int to a void* calling the pthead_create function, you should convert it back to an integer type. So, this line is wrong :

int *id=(int *)s;

it should be :

int id = (int)s; 

Consider this example where the argument for the thread function is zero.

s=0; therefore  ---> *id=(int*)0; // Null pointer 

This is a pointer to the address zero. When you try to deference it, you will likely get an segmentation fault.

The best way to do this is by using the intptr_t type. This type has the same size of a pointer (not int) in every architecture. It is defined as follows :

Integer type capable of holding a value converted from a void pointer and then be converted back to that type with a value that compares equal to the original pointer.

So you can do something like this:

#include <stdint.h>

void *threadfunc(void *param)
{
    int id = (intptr_t) param;
    ...
}

int i, r;
r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i);

(This example code has been taken from : How to cast an integer to void pointer?)

However, there is not guarantee that the size of int is the same of the size of intptr_t, but it's really unlikely that some data is lost in the conversion process.

EDIT

Additional errors :

  • float **Aa, **Bb, **Cc; are not initialised.
  • start and end exceeds the limit of the array. The matrix rows are not allocated in consecutive memory areas.
  • if the thread function is working on a chunks of the matrix, there is not point to go through all the values of the matrix A and B. You might want only the internal loop which, in theory, should work on the part of matrix assigned to it.

I would consider to rewrite the code for the matrix multiplication because the algorithm is wrong.

4

Correct way to achieve this is by referencing the variable "i" (check ):

pthread_create(&thread_id[i], NULL, prod, (void *)&i);
2

You want to cast integer, short, or char and set a pointer to that value use the reinterpret_cast() call. We used to just (void*) the value and the older compilers were happy, but the new versions, for example g++ 4.8.5, know the value is not the right size for a pointer. reinterpret_cast is just like a cast but it resized it so the compile doesn't complain.

For example:

int i = 3;
pointer void * ptr;

ptr = (void*)i;                    // will generate the warning
ptr = reinterpret_cast<void*>(i);  // No warning is generated

X11 example getting a character out of addr and then setting XTPOINTER to it.

val = (XTPOINTER)(*(char*)toVal.addr);                   //  warning
val = reinterpret_cast<XTPOINTER>(*(short*)toVal.addr);  // No warning
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Robert Thorne
Author

Robert Thorne

Robert Thorne covers electric vehicle innovations, autonomous driving systems, global mobility trends, and automotive engineering developments.