Salve a tutti ragazzi , sto facendo un esercizio molto standard in cui ho un buffer con un solo campo e ho 5 processi produttori e 5 processi consumatori che si sincronizzano mediante un monitor di tipo signal and return : prima deve produrre un produttore , poi può consumare un consumatore e così via di seguito fino alla fine .
Io ho creato i file main.cpp,body.cpp,header.h,Makefile mentre quelli relativi al monitor mi sono stati già dati corretti e funzionanti. Il problema è che ottengo sempre l'errore "Errore di segmentazione (core dump creato)"


Il progetto prevede i seguenti file :

main.cpp :
[SPOILER]
codice:
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include "monitor.h"
#include "header.h"


using namespace std;


int main(){


//******PARTE DICHIARATIVA*******
pid_t pid;
key_t shmkey;
int shmid;
int stato;
int num_proc,num_cons,num_prod;
p_c_monitor* m;




//******PARTE ESECUTIVA**********


//inizializzo il numero di processi , di consumatori e di produttori
num_cons = 5 ; 
num_prod = 5 ; 
num_proc = num_cons + num_prod;


//inizializzo il monitor
init_monitor( &(m->M), NUMCOND );


//inizializzo il valore della chiave della shm che ospiterà la struct p_c_monitor
shmkey = IPC_PRIVATE;


//genero tale shm
shmid = shmget(shmkey, sizeof(p_c_monitor),IPC_CREAT|0664);


//attacco la shm 
m = (p_c_monitor*) (shmat(shmid,0,0));


//inizializzo le variabili condition della mia struttura
m->ok_prod=1;
m->ok_cons=0;




//genero num_proc processi figli , metà  produttori e metà consumatori
for(int i=0; i < num_proc ; i++){
	if(pid==0){
		if( (i%2)==0 ){ //Processo Conumatore
			cout<<"sono il processo consumatore numero: "<<getpid()<<endl;
			sleep(1);
			consumazione(m);
		}		
		else{ //Processo Produttore
			cout<<"sono il processo produttore numero: "<<getpid()<<endl;
			sleep(1);
			produzione(m);			
		}
		exit(0);
	}
}


//attendo la terminazione dei figli
for(int i=0; i < num_proc ; i++){
	pid = wait(&stato);
	if(pid==-1)
		cout<<"Errore\n";
	else
		cout<<"Il figlio numero: "<<pid<<" è terminato con stato: "<<stato<<endl;
}


//Rimuovo le strutture
shmctl(shmid,IPC_RMID,0);
remove_monitor( &(m->M) );
return 0; 


}
[/SPOILER]

header.h
[SPOILER]
codice:
/*Si vuole realizzare il classico problema produttore consumatore con un unico buffer attraverso un'applicazione multiprocesso dove n processi sono produttori ed m processi sono consumatori e si vuole usare il costrutto monitor implementato come signal_and_return*/


//Definisco IL NUMERO delle variabili condition che mi servirà per la monitor_init e gli id che voglio usare per essi
#define NUMCOND 2 
#define OK_PROD 0
#define OK_CONS 1 


//definisco il monitor includendovi anche il buffer e l'implementazione di monitor già fatta e definisco il tipo di messaggio
typedef long msg;


typedef struct{
//variabili condition: 
int ok_prod;
int ok_cons; 


//buffer:
msg messaggio; 


//monitor da usare già implementato: 
Monitor M;
} p_c_monitor; 


//definisco le funzioni 
void produzione(p_c_monitor*);
void inizio_produzione(p_c_monitor*);
void fine_produzione(p_c_monitor*);
void consumazione(p_c_monitor*);
void inizio_consumazione(p_c_monitor*);
void fine_consumazione(p_c_monitor*);
[/SPOILER]

body.cpp
[SPOILER]
codice:
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include "monitor.h"
#include "header.h"
#include <sys/time.h>


using namespace std;


void produzione(p_c_monitor* m){
inizio_produzione(m);
struct timeval t1;
struct timezone t2;
gettimeofday(&t1,&t2);
m->messaggio = t1.tv_usec;
cout<<"Valore prodotto : "<<m->messaggio<<endl;
fine_produzione(m);
}




void inizio_produzione(p_c_monitor* m){
enter_monitor(&(m->M));
if( !(m->ok_prod) ) //se ok_prod non è verificata , è falsa , quindi non posso produrre, mi devo sospendere su questa condizione
	wait_condition(&(m->M),OK_PROD);
	
}




void fine_produzione(p_c_monitor* m){
//aggiorno i valori delle variabili logiche stabilendo che il buffer è pieno e non si può più produrre ma si può consumare
m->ok_prod = 0;
m->ok_cons = 1; 
//faccio una signal per sbloccare i consumatori in coda
signal_condition( &(m->M),OK_CONS);
//esco dal monitor
leave_monitor(&(m->M));
}




void consumazione(p_c_monitor* m){
inizio_consumazione(m);
cout<<"Il messaggio consumato è: "<<m->messaggio<<endl;
fine_consumazione(m);


}




void inizio_consumazione(p_c_monitor* m){
enter_monitor(&(m->M));
if(!(m->ok_cons))
	wait_condition( &(m->M),OK_CONS);
}




void fine_consumazione(p_c_monitor* m){
m->ok_prod = 1; 
m->ok_cons = 0;
signal_condition( &(m->M) , OK_PROD);
leave_monitor(&(m->M));
}
[/SPOILER]

monitor.h
[SPOILER]
codice:
/***PROTOTIPI DELLE PROCEDURE PER LA REALIZZAZIONE DEL COSTRUTTO MONITOR***/




typedef struct {
  int mutex;
  int num_var_cond;
//id del gruppo sem associati alle var.cond
  int id_conds;     
//array delle variabili condition_count
   int *cond_counts; 
//identificativo memoria condivisa
   int id_shared;    
} Monitor;


//monitor e numero di variabili condition
void init_monitor (Monitor*, int); 
void enter_monitor(Monitor*);
void leave_monitor(Monitor*);
void remove_monitor(Monitor*);
void wait_condition(Monitor*,int);
void signal_condition(Monitor*,int);
[/SPOILER]

monitor.cpp
[SPOILER]
codice:
/*************************************Monitor*************************************************/
// Implementazione di un Monitor 




#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <stdio.h>
#include <unistd.h>
#include "monitor.h"




//Funzioni di utilita' private alla libreria Monitor


static void Wait_Sem(int, int);
static void Signal_Sem (int,int);
static int Queue_Sem (int,int);   //restituisce il num di processi in attesa su un semaforo




/********************IMPLEMENTAZIONE DELLE PROCEDURE***********************/


void init_monitor (Monitor *M,int num_var){
    int i;
    M->num_var_cond=num_var;
    M->mutex=semget(IPC_PRIVATE,1,IPC_CREAT|0664);
    M->id_conds=semget(IPC_PRIVATE,num_var,IPC_CREAT|0664);
    semctl(M->mutex,0,SETVAL,1);
    for (i=0;i<num_var;i++)
         semctl(M->id_conds,i,SETVAL,0);
    M->id_shared=shmget(IPC_PRIVATE,num_var*sizeof(int),IPC_CREAT|0664);
    M->cond_counts=(int*) (shmat(M->id_shared,0,0));
    for (i=0;i<num_var;i++)
        M->cond_counts[i]=0;
#ifdef DEBUG_
    printf("Monitor inizializzato con %d condition variables. Buona Fortuna ! \n",num_var);
#endif


} 






void enter_monitor(Monitor * M){


#ifdef DEBUG_
    printf("<%d> Tentativo di ingresso nel monitor... \t",getpid() );
#endif
     Wait_Sem(M->mutex,0);
#ifdef DEBUG_
    printf("<%d> Entrato nel monitor \n",getpid() );
#endif


}




void leave_monitor(Monitor* M){
#ifdef DEBUG_
    printf("<%d> Uscito dal monitor  \n", getpid());
#endif
     Signal_Sem(M->mutex,0);
}




void remove_monitor(Monitor* M){
    semctl(M->mutex,0,IPC_RMID,0);
    semctl(M->id_conds,M->num_var_cond,IPC_RMID,0);
    shmctl(M->id_shared,IPC_RMID,0);
#ifdef DEBUG_
    printf(" \n Il Monitor è stato rimosso ! Arrivederci \n", getpid());
#endif


}


void wait_condition(Monitor* M,int id_var){
#ifdef DEBUG_
    printf("<%d> -Monitor- invocata la wait sulla condition numero %d\n", getpid(), id_var);
#endif
      M->cond_counts[id_var]=M->cond_counts[id_var]+1;
      Signal_Sem(M->mutex,0);
      Wait_Sem(M->id_conds,id_var);
      M->cond_counts[id_var]=M->cond_counts[id_var]-1;
}


void signal_condition(Monitor* M,int id_var){
#ifdef DEBUG_
            printf("<%d> -Monitor- tentativo di signal; n.ro proc. in attesa sulla cond. n. %d = %d\n", getpid(), id_var,M->cond_counts[id_var]);
#endif     


      if(M->cond_counts[id_var]>0) {
            Signal_Sem(M->id_conds,id_var);
#ifdef DEBUG_
            printf("<%d> -Monitor- invocata la signal sulla condition numero %d\n", getpid(), id_var);
#endif
     } else {
            Signal_Sem(M->mutex,0);
#ifdef DEBUG_
            printf("<%d> -Monitor- invocata la signal sul mutex \n", getpid());
#endif
      }
 }




/********************IMPLEMENTAZIONE DELLE PROCEDURE SEMAFORICHE***********************/


void Wait_Sem(int id_sem, int numsem)     {
       struct sembuf sem_buf;
       sem_buf.sem_num=numsem;
       sem_buf.sem_flg=0;
       sem_buf.sem_op=-1;
       semop(id_sem,&sem_buf,1);   //semaforo rosso
}


// restituisce il numero di processi in attesa sul semaforo
int Queue_Sem(int id_sem, int numsem)     {
	return (semctl(id_sem,numsem,GETNCNT,NULL));
}


void Signal_Sem (int id_sem,int numsem)     {
       struct sembuf sem_buf;
       sem_buf.sem_num=numsem;
       sem_buf.sem_flg=0;
       sem_buf.sem_op=1;
       semop(id_sem,&sem_buf,1);   //semaforo verde
}
[/SPOILER]

Makefile
[SPOILER]
codice:
start: main.o body.o monitor.o
	g++ -o start main.o body.o monitor.o


main.o: main.cpp header.h
	g++ -c main.cpp


body.o: body.cpp header.h
	g++ -c body.cpp


monitor.o: monitor.h monitor.cpp
	g++ -c monitor.cpp


clean: 
	rm -f *.o
	rm -f ./start
	rm -f *~
[/SPOILER]

Ho già individuato la parte critica , ossia :
codice:
init_monitor( &(m->M), NUMCOND );
in main.cpp, infatti commentando quell'unica riga di codice , non ricevo più l'errore " Errore di segmentazione (core dump creato) " ,
Grazie mille in anticipo a chiunque possa aiutarmi.