Ciao a tutti! Io e la mia collega abbiamo bisogno del vostro aiuto!
Dobbiamo fare una versione (molto semplificata) di Space Invaders e usare i thread per la comunicazione tra i processi..Il problema è che durante l'esecuzione, il programma si blocca o a causa della segmentation fault o perchè viene sollevata la floating point exception..Il motivo??boooh!!!Vi posto il codice..è un po' lunghetto, ma ci sono tanti commenti così potete capire cosa abbiamo fatto..Vi prego..aiutateci!!
codice:
#include <stdio.h>
#include <time.h>
#include <curses.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <semaphore.h>
#include <unistd.h>

#define PASSO 1 //entita' dello spostamento del nemico
#define SINISTRA 68 // freccia sx
#define DESTRA 67 // freccia dx
#define SGANCIA 32 // spazio
#define MAXX 80 // numero di colonne dello schermo
#define MAXY 24 // numero di righe dello schermo
#define M 2 // numero di nemici di 1° livello
#define G 4 // numero di nemici di 2° livello per gruppo
#define BUFFER_DIM 100000


//** Prototipi funzioni **//
void * astronave_func(void * arg);
void * missile_func(void * arg);
void * nemico_func(void * arg);
void * nemico2_func(void * arg);
void * bomba_func(void * arg);
void * controllo_func(void * arg);


//**Struttura per la comunicazione fra figli e padre**//
typedef struct pos
     {
        char c; // soggetto che invia il dato: astronave, nemico, bomba o missile
        int x; // coordinata x
        int y; // coordinata y
        int DIRX; // direzione del nemico di 2° livello
        int p; // posizione del nemico all'interno del vettore v[] che rappresenta il gruppo di nemici di primo livello
        int pid; // pid del processo
        int vita; // 0: il nemico è morto; 1: il nemico è vivo
	int xi; // coordinata x del primo nemico di secondo livello
        int xf; // coordinata x dell'ultimo nemico di secondo livello
        int nem_vivi[G]; // vettore che indica lo stato di vita dei nemici di secondo livello all'interno di ciascun gruppo
        int g; // rappresenta il numero del gruppo a cui appartiene il nemico di secondo livello
        int n; // rappresenta il numero assegnato al nemico di 2° livello all'interno del proprio gruppo
      } pos;


typedef struct argomenti // struttura per passare più argomenti ad una funzione thread
     {
	int x; // posizione in x (dell'astronave o del nemico)
	int y; // posizione in y (dell'astronave o del nemico)
	int i; // indice i
     } args;


//** Inizializzazioni buffer e semafori **//
pos buffer[BUFFER_DIM]; // buffer condiviso
int IN = 0; // variabile che indica le posizioni occupate nel buffer
int OUT = 0; // variabile che indica le posizioni disponibili nel buffer
sem_t presenti, disponibili; // variabili che indicano il valore del semaforo, ovvero la presenza o meno di job disponibili
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // mutex per evitare la race condiction


main()
{
initscr();      // inizializzazione dello schermo
start_color(); // per l'utilizzazione dei colori
noecho();     // i caretteri corrispondenti ai tasti premuti non saranno visualizzati sullo schermo del terminale
curs_set(0); // nasconde il cursone


sem_init(&disponibili, 0, BUFFER_DIM); // inizializzazione semaforo disponibili
sem_init(&presenti, 0, 0); // inizializzazione semaforo presenti
//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // inizializzazione mutex

srand(time(NULL));

pthread_t astronave_id, nemico_id[M], controllo_id;
int i;

//creazione dei thread
pthread_create(&astronave_id, NULL, &astronave_func, NULL);
for(i=0;i<M;i++)
     pthread_create(&nemico_id[i], NULL, &nemico_func, &i);

//evita che vengano deallocati dati indispensabili ai thread alla terminazione del main
//pthread_join(astronave_id, NULL);

pthread_create(&controllo_id, NULL, &controllo_func, NULL);
pthread_join(controllo_id, NULL);

/** Siamo usciti dal controllo e si terminano i procssi figli. Ripristina il normale modo operativo dello schermo **/
endwin();

return(0);
}

/** Funzione ASTRONAVE **/
void * astronave_func(void * arg)
{
pos pos_astronave;
args pos;
pthread_t missile_id[2]; // l'astronave spara contemporaneamente due missili:uno a destra e uno a sinistra
int i;

pos_astronave.c='#';
pos_astronave.x=MAXX/2;
pos_astronave.y=MAXY-1;
pos_astronave.pid=pthread_self();

sem_wait(&disponibili);
pthread_mutex_lock(&mutex);
buffer[IN] = pos_astronave;
IN=(IN+1)%BUFFER_DIM;
sem_post(&presenti); // incrementa il semaforo
pthread_mutex_unlock(&mutex);

while(1)
     {
      char c;
      switch(c=getch()) { //gestione movimento o sgancio dei missili da parte dell'astronave
        case SINISTRA: if(pos_astronave.x>0){
                                      pos_astronave.x-=1; 				      
					     } // fine if(pos_astronave.x>0)
                                   break;
        case DESTRA: if(pos_astronave.x<MAXX-1){
                                    pos_astronave.x+=1;
						 }
                                 break;
        case SGANCIA: for(i=0;i<2;i++){
					pos.i=i;
					pos.x=pos_astronave.x;
					pos.y=pos_astronave.y;
				    	pthread_create(&missile_id[i], NULL, &missile_func, &pos); 
					//pthread_join(missile_id[i], NULL); 
				      }
                                  break;
                                } // fine switch gestione movimento

	sem_wait(&disponibili);
	pthread_mutex_lock(&mutex);
	buffer[IN] = pos_astronave;
	IN=(IN+1)%BUFFER_DIM;
	sem_post(&presenti); // incrementa il semaforo
	pthread_mutex_unlock(&mutex);

    } // fine while
} // fine Funzione Astronave


/** Funzione MISSILE **/
void * missile_func(void * arg)
{
    pos pos_missile;
    args * pos = (args *)arg;
    int i = pos->i;

    pos_missile.c='*';                /*Effettuo il primo assegnamento*/
    pos_missile.pid=pthread_self();
    pos_missile.p=i;   // può essere 0 o 1 e indica quella che sarÃ_ la direzione del missile (dx o sx)

    if(i%2) // se i è dispari
       pos_missile.x=pos->x +PASSO; // vÃ_ a sinistra
    else // altrimenti
       pos_missile.x=pos->x -PASSO; // vÃ_ a destra
 
     pos_missile.y=pos->y-1;

    sem_wait(&disponibili);
    pthread_mutex_lock(&mutex);
    buffer[IN] = pos_missile;
    IN=(IN+1)%BUFFER_DIM;
    sem_post(&presenti); // incrementa il semaforo
    pthread_mutex_unlock(&mutex);



    if(i%2)   //se i=1 il missile vÃ_ a sinistra altrimenti a destra
      while(1)
              {
                pos_missile.x+=PASSO;
                pos_missile.y-=PASSO;
             
		sem_wait(&disponibili);
                pthread_mutex_lock(&mutex);
		buffer[IN] = pos_missile;
		IN=(IN+1)%BUFFER_DIM;
		sem_post(&presenti); // incrementa il semaforo
    		pthread_mutex_unlock(&mutex);

                usleep(200000);
              }
    else
      while(1)
              {
                pos_missile.x-=PASSO;
                pos_missile.y-=PASSO;
                
		sem_wait(&disponibili);
                pthread_mutex_lock(&mutex);
                buffer[IN] = pos_missile;
		IN=(IN+1)%BUFFER_DIM;
		sem_post(&presenti); // incrementa il semaforo
    		pthread_mutex_unlock(&mutex);

                usleep(200000);
              }

} // fine Funzione Missile


/** Funzione BOMBA **/
void * bomba_func(void * arg)
{
   pos pos_bomba;
   args * pos = (args *)arg;
 
   pos_bomba.c='o';   //inizializzo: la bomba parte dalla stessa colonna del nemico una posizione in avanti
   pos_bomba.x=pos->x;
   pos_bomba.y=pos->y +PASSO;
   pos_bomba.pid=pthread_self();

   sem_wait(&disponibili);
   pthread_mutex_lock(&mutex);
   buffer[IN] = pos_bomba;
   IN=(IN+1)%BUFFER_DIM;
   sem_post(&presenti); // incrementa il semaforo
   pthread_mutex_unlock(&mutex);
   
      while(1)
        {
              pos_bomba.y+=PASSO;

	      sem_wait(&disponibili);
              pthread_mutex_lock(&mutex);
	      buffer[IN] = pos_bomba;
	      IN=(IN+1)%BUFFER_DIM;
	      sem_post(&presenti); // incrementa il semaforo
    	      pthread_mutex_unlock(&mutex);
              usleep(300000);
         }

}//fine funzione bomba


/** Funzione NEMICO **/
void * nemico_func(void * arg)
{
pos pos_nemico;
int i = *((int *)arg);
int dx,dy; // spostamenti in x e y;
int SOGLIAX; // soglia oltre la quale il nemico non può andare - può essere 1 o MAXX-1
int DIRX; // direzione in x - se dirx=1 vÃ_ a destra, se dirx=-1 va a sinistra
int time_giu=0; // contatore per far scendere il nemico
int SOGLIA_GIU=10*(0+rand()%4)+i*5; // soglia per far scendere il nemico di una riga
int time_bomb=1; // contatore per far sganciare una bomba
int SOGLIA_BOMB=30+i*(0+rand()%5); // soglia per far sganciare la bomba
args pos;
pthread_t bomba_id;

pos_nemico.c='$';
pos_nemico.p=i;
pos_nemico.pid=pthread_self();
pos_nemico.y=1; // i nemici partono tutti sulla stessa riga
pos_nemico.x=9+(i*20); // ma distanziati

if(!(i%2)) // se il numero assegnato al nemico è pari
  {
    DIRX=1; // vÃ_ a destra
    SOGLIAX=MAXX-1; // e la soglia max in x è MAXX-1
  }
else // altrimenti
   {
     DIRX=-1; // vÃ_ a sinistra
     SOGLIAX=1; // e la soglia max in x è 1
   }

sem_wait(&disponibili);
pthread_mutex_lock(&mutex);
buffer[IN] = pos_nemico;
IN=(IN+1)%BUFFER_DIM;
sem_post(&presenti); // incrementa il semaforo
pthread_mutex_unlock(&mutex);

while(1)
{
 
      if(pos_nemico.x==SOGLIAX) // se il nemico sbatte contro una parete laterale
       {
         DIRX*=-1; // cambio la direzione
         if(SOGLIAX==MAXX-1) // se la nuova direzione è destra
            SOGLIAX=1; // la soglia è MAXX-1
         else // altrimenti
            SOGLIAX=MAXX-1; // la soglia è 1
       }   

     if(DIRX==1) // se la direzione è destra
      dx=PASSO; // il suo spostamento sarÃ_ di PASSO
    else // altrimenti
      dx=-PASSO; // il suo spostamento sarÃ_ di -PASSO
      
    pos_nemico.x+=dx; // scriviamo la posizione in x del nemico

    if(!(time_giu%SOGLIA_GIU)) // ad intervalli regolari
       {
         dy=PASSO; // il nemico avanza di PASSO verso la soglia massima in Y
         time_giu=1; // riazzero il contatore
       }
    else
       {
         dy=0; // il nemico non avanza verso la soglia massima in Y
         time_giu++; // aggiorno il contatore per la discesa del nemico
       }

    pos_nemico.y+=dy; // scriviamo la posizione in y del nemico

    sem_wait(&disponibili);
    pthread_mutex_lock(&mutex);
    buffer[IN] = pos_nemico;
    IN=(IN+1)%BUFFER_DIM;
    sem_post(&presenti); // incrementa il semaforo
    pthread_mutex_unlock(&mutex);


    if(!(time_bomb%SOGLIA_BOMB)){ // ad intervalli regolari
	pos.x = pos_nemico.x;
	pos.y = pos_nemico.y;
        pthread_create(&bomba_id, NULL, &bomba_func, &pos); 
	//pthread_join(bomba_id, NULL);
                                }
    time_bomb++; // aggiorno il contatore per la bomba

    usleep(300000);

} // fine while;

} // fine Funzione Nemico
(continua...)