Reputation: 159
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
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
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