EmiliOrtega
EmiliOrtega

Reputation: 159

cast to pointer from integer of different size -wint-to-pointer-cast

Hello i have the next problem in my code:

"cast to pointer from integer of different size -wint-to-pointer-cast"

This problem is in this line of code

pthread_create(&filos[i], NULL, (void *)filosofos,(void *) i);

Specifically in (void *) i

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

#define N 5               //num. de filosofos
#define IZQ (i-1)%N      //vecino izquierdo de i
#define DER (i+1)%N      //vecino derecho de i
#define PENSANDO 0
#define CON_HAMBRE 1
#define COME 2


pthread_t filos[N];       //hilos que representan a los filósofos
sem_t mutex ;             //semáforo para la sección crítica
sem_t s[N];               //semáforos para los filósofos
int estado [N] ;          //estado actual de cada filósosfo


/* 
    el filosofo i va a perder el tiempo... (va a pensar)
 */
void pensar (int i) 
{
  int t ;
  t = rand() % 11;
  printf("Filosofo %d pensando \n", i) ;
  estado[i] = PENSANDO;
  sleep (t) ;
}


/* 
    El filosofo i, va a comer !!!!!!!!
 */
void comer (int i) 
{
  printf("Filósofo %d esta comiendo un caballo \n", i);
  estado[i] = COME;
  sleep (5);
}


/* 
    Verifica que pueda tomar ambos tenedores
*/
void verifica(int i) 
{
  if( estado[i]==CON_HAMBRE && estado[IZQ]!=COME && estado[DER]!=COME ){
    estado[i] = COME;
    printf("Filósofo %d comiendo\n", i) ;
    sem_post(&s[i]);
  }
}


/* 
    El filosofo i intenta tomar los  tenedores
 */
void toma_tndrs(int i)
{

  sem_wait(&mutex);             //entra a la sección crítica, hace uso del semaforo
  estado[i] = CON_HAMBRE;      //dice: tengo mucha hambre!!!!!!!!!!
  verifica(i);                 // verifica que pueda tomar los tenedores
  sem_post(&mutex);            //sale de la sección crítica y el sem. puede permitir la entrada a alguien más
  sem_wait(&s[i]);            //se bloquea si no consiguió los tenedores
}


/* 
    el filosofo i dejará los tenedores
 */
void deja_tndrs(int i)
{

  sem_wait(&mutex);       // de nuevo entra a la sección critica
  estado[i] = PENSANDO;  //deja de comer y se pone a pensar
  verifica(IZQ);        
  verifica(DER);
  sem_post(&mutex);
}


/* 


 */
void * filosofos (int i)
{
  int j ;


  for (; ; )
    {
      pensar(i) ;
      toma_tndrs(i) ;
      comer(i) ;
      deja_tndrs(i) ;
    }
}


main()
{
  int i ;


  for(i = 0; i < 5; i++){
    sem_init (&s[i], 0, 1);


    estado[i] = PENSANDO ;
  }


  sem_init (&mutex, 0, 1);

  //creamos un hilo de ejecucion para cada filosofo, que ejecuta filosofos()
  for (i=0; i<N; i++)
    pthread_create(&filos[i], NULL, (void *)filosofos,(void *) i);

  //cada hilo espera a que terminen los demás y libera los recursos
  for (i=0; i<N; i++){
    pthread_join(filos[i],NULL);
  }

}

Upvotes: 4

Views: 10677

Answers (2)

Some programmer dude
Some programmer dude

Reputation: 409166

Assuming it's the cast of the i variable that causes the problem, first cast it to an integer type that is larger than int and at the same time large enough to hold a pointer.

One such type, designed for the very purpose of being large enough to hold any integer or pointer, is intptr_t, described in e.g. this fixed-width integer reference.

The cast would then look like

(void *) (intptr_t) i

In the thread function you do the opposite, first cast to intptr_t and then to int.

void * filosofos (void *p)
{
    int i = (int) (intptr_t) p;

    ...

    return NULL;
}

Note that I changed the signature of the thread function to be correct, it takes a void * argument, and this makes a whole lot difference on systems where sizeof(int) != sizeof(void *), which seems to be true in your case. Also note that I return a NULL at the end of the function. That's because the thread function is declared (and specified) to return a pointer. Not returning a value from a function declared to do so leads to undefined behavior.


For those curious, while I would normally not recommend casting an integer to a pointer like this, there are exceptions to everything and this is one of the few cases (if not the only one) where such a cast is acceptable.

Many still look down on such a solution, but still use it since it's easier than the whole malloc-copy-free circus that's otherwise needed.

A solution using dynamic allocated memory for the value would look something like this:

  • Thread creation

    // Allocate memory for the index
    int *p = malloc(sizeof i);
    if (p == NULL)
    {
        // TOOD: Handle error! (Left as an exercise to the reader)
    }
    
    // Copy the value
    *p = i;
    
    // And create the thread
    pthread_create(&filos[i], NULL, &filosofos, p);  // Note: no cast needed
    
  • In the thread function

    void * filosofos (void *p)
    {
        int i = *(int *) p;
        free(p);
    
        ...
    
        return NULL;
    }
    

While this solution is more "correct", it is less readable which means it's less maintainable; It has more code which means more chances of errors; And it has the possibility of a memory leak if the free call is forgotten (which sooner or later will happen).

Upvotes: 7

Sam Pagenkopf
Sam Pagenkopf

Reputation: 258

You're converting i to a void pointer without creating a reference to it. I'm not a spanish speaker, but I can assume you meant to do:

pthread_create(&filos[i], NULL, (void *)filosofos, (void *)&i);

Otherwise, you've created a reference to memory address i, and there's nothing you can touch in memory with such a low address :P

Also, casting explicitly to and from void pointers is a something to avoid.

https://www.tutorialspoint.com/cprogramming/c_pointers.htm

Try learning a bit more about pointers.

Upvotes: 0

Related Questions