PDA

Visualizza la versione completa : [C++] Errore di segmentazione (core dump creato)


Warioss
20-11-2017, 23:24
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 :

#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;


}




header.h

/*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*);

body.cpp

#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));
}

monitor.h

/***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);






monitor.cpp

/*************************************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),I PC_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
}

Makefile

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 *~

Ho già individuato la parte critica , ossia :

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.

oregon
21-11-2017, 07:29
Il problema è che m in quel momento è un puntatore non inizializzato.

Warioss
21-11-2017, 09:50
Il problema è che m in quel momento è un puntatore non inizializzato.
Oh grazie infinite Oregon!! Sono un vero stupido ... sarà stata per l’ora , ovviamente ho chiamato la init_monitor con m ma non l’ho inizializzata m ... allora ho spostato semplicemente le istruzioni di creazione ed inizializzazione della shared menory delle righe successive prima dell’ init_monitor ed infatti ora funziona alla perfezione il programma .

Grazie tante , sono stato proprio stupido 😂
Ciao , alla prossima.

Loading