Visualizzazione dei risultati da 1 a 3 su 3
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2015
    Messaggi
    32

    [C++] Errore di segmentazione (core dump creato)

    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.

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    Il problema è che m in quel momento è un puntatore non inizializzato.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Utente di HTML.it
    Registrato dal
    Nov 2015
    Messaggi
    32
    Quote Originariamente inviata da oregon Visualizza il messaggio
    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.
    Ultima modifica di Warioss; 21-11-2017 a 10:56

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.