Problema segmentation fault .c

di il
29 risposte

Problema segmentation fault .c

Salve Ragazzi , sto scrivendo un piccolo programmino più per diletto che per altro, e mi sono imbattuto in un paio di problemi, volete darmi una mano?

Vi posto il programmino su pastebin per non appesantire il 3d,

http://pastebin.com/UNqvHr9

Dunque il problema risiede nella funzione nuovofile.
In particolare nel Loop while: una volta finita la chiamata alla funzione calcolaconsumo :
- fwrite non salva nulla sul file ListaDispositivi.txt
- qualunque entrata nella scanf (%s, nuovodispositivo) genera un errore di segmentation fault.

Sapete dirmi dove sbaglio? il programma compila correttamente quindi è ovviamente un errore logico che non vedo.
Help!

29 Risposte

  • Re: Problema segmentation fault .c

    Nuovodispositivo è un intero non una stringa
  • Re: Problema segmentation fault .c

    Ha ragione, corretta la
    scanf("%d", nuovodispositivo);
    tuttavia dà il medesimo errore.
  • Re: Problema segmentation fault .c

    Beh, la scanf prevede un puntatore alla variabile ...
  • Re: Problema segmentation fault .c

    Ehm...& aggiunto. Ok mentre per la fwrite cosa mi puoi dire?

    chiedo venia è da sta mattina che sono al pc, ma dopotutto , sono qui per imparare
  • Re: Problema segmentation fault .c

    Spiega cosa si dovrebbe trovare nel file ... spiega come dovrebbe funzionare il programma, cosa inserire, cosa ottenere ...
  • Re: Problema segmentation fault .c

    Allora nel file ListaDispositivi.txt dovrebbero trovarsi i dati della Struct puntata da Dispo (cioè Device).

    Dato che ho passato alla funzione calcola consumo Dispo , cioè &Device lui anche se non mi ritorna esplicitamente nulla modifica comunque le voci della struct principale Device.

    Quindi quando chiedo a fwrite di salvare Dispo nel file, gli sto chiedendo di salvare Device corretto?
  • Re: Problema segmentation fault .c

    Mi dispiace Emanuele ma ci sono un bel po' di errori "importanti".

    Tanto per cominciare non allochi mai lo spazio in memoria per le strutture che utilizzi, né staticamente né dinamicamente. Hai solamente i puntatori ma questi non puntano a nulla.

    In secondo luogo, passi dei parametri alle funzioni che non dovrebbero essere passati o nel modo sbagliato.

    Infine devi sempre accertarti di eseguire la fclose, cosa che non fai sempre.

    Ovviamente il problema *più importante* che devi risolvere assolutamente è il primo ... l'allocazione dello spazio.
  • Re: Problema segmentation fault .c

    Quindi per ogni dispositivo devo creare un nuovo puntatore che possa utilizzare con la malloc per allocare la memoria per una nuova struttura giusto?
    Perciò mi conviene creare una lista allocandola ogni volta che viene creato un nuovo dispositivo.
    Se ho capito bene mi aspetta una bella seratina
  • Re: Problema segmentation fault .c

    Probabilmente non ti è chiara la gestione delle "liste".

    Il primo puntatore alla lista ce l'hai. E ogni elemento ha un puntatore nella struttura che deve puntare al prossimo elemento o essere a NULL se è l'ultimo.

    Quindi i puntatori li hai tutti e non devi crearne. Devi solo allocare lo spazio con la malloc (C) o con la new (C++).

    E non devi dimenticare di liberarla con free (C) o delete (C++).
  • Re: Problema segmentation fault .c

    Forse mi sono espresso male, volevo dire che ogni volta che devo aggiungere un dispositivo alla lista devo creare una nuova allocazione di memoria per la struttura del dispositivo.
    Penso di aver capito e ci sto già lavorando. Grazie appena finisco se ho problemi griderò aiuto
  • Re: Problema segmentation fault .c

    Ritorno a voi con un programma modificato penso al più abb correttamente anche se alcune funzioni sono ancora in sviluppo . Come consigliatomi ho cercato di risolvere il problema dell'allocazione di memoria. ora vi posto il programma e vi spiego l'inghippo in cui sono caduto
    //  Questo Programma Calcola il Consumo di vari dispositivi , esporta il file in un file di testo
    //  visualizza la lista di dispositivi presenti nel file  o elimina dati dal file.
    
    #include <stdio.h>
    #include <malloc.h>
    
    struct Dispositivo{    	// typedef struct dispositivo Disp;
     	int ID;
        char nome[10];
    	int watt;
    	float TotaleNetto;
    	float Totale;
    	struct Dispositivo *nextPtr;
    };
    
    typedef struct Dispositivo TipoDispositivo; //viene ridefinito "struct Dispositivo" come TipoDispositivo
    typedef TipoDispositivo *DispPtr;  //viene definito un tipo puntatore "TipoDispositivo *" 
    
    void menu (void);
    void salvalista (TipoDispositivo *);
    //void stampadispositivi (void);
    //void eliminadato (void);
    void calcolaconsumo(TipoDispositivo *);
    void nuovodispositivo(TipoDispositivo *);
    
    
    int main(){
    
    
    TipoDispositivo *DispoPtr= NULL; 
    int scelta;
    
    while (scelta =!0) {
    menu();
    scelta = getchar();
    switch (scelta){
        
        case '1' :
        nuovodispositivo(DispoPtr);
        printf("Caratteristiche DispoPtr:\n ID : %d\n Nome : %s\n Totale Netto : %f\n Totale : %f\n",(*DispoPtr).ID,(*DispoPtr).nome,(*DispoPtr).TotaleNetto,(*DispoPtr).Totale );
        break;
    	case '4' :
    	salvalista(DispoPtr); //&Device
    	break;
    	case '2' :
    	//stampadispositivi();
    	break;
    	case '3' :
    	//eliminadato();
    	break;
    	default : printf("Scelta non corretta");
    	break;
    		  }
    }
    
    return 0;
    
    }
    
    //------------------------------------------------------//
    void menu (void) {
    
    printf("-----Menù-----\nInserire un numero per determinare l'azione da intraprendere\n");
    printf("1)Aggiungi un dispositivo alla lista\n2)Stampa lista dei dispositivi \n3)Elimina registro\n4)Salva la lista in un file\n");}
    
    //------------------------------------------------------//
    void nuovodispositivo (TipoDispositivo *DevicePtr) {
         
    TipoDispositivo *newDevicePtr;
    TipoDispositivo *previousDevicePtr;
    TipoDispositivo *currentDevicePtr;
    
    newDevicePtr = malloc(sizeof(TipoDispositivo));
    
    if( newDevicePtr !=NULL) {
    
        calcolaconsumo(newDevicePtr);
        printf("Caratteristiche newDevicePtr:\n ID : %d\n Nome : %s\n Totale Netto : %f\n Totale : %f\n",(*newDevicePtr).ID,(*newDevicePtr).nome,(*newDevicePtr).TotaleNetto,newDevicePtr->Totale );
        (*newDevicePtr).nextPtr= NULL;
        previousDevicePtr = NULL;
        currentDevicePtr= DevicePtr;
        printf("cucu\n"); 
        while (currentDevicePtr!=NULL && (*currentDevicePtr).ID >(*newDevicePtr).ID){
              previousDevicePtr=currentDevicePtr;
              currentDevicePtr=(*currentDevicePtr).nextPtr;
              printf("cucu2\n");}
              if(previousDevicePtr == NULL){ 
                  (*newDevicePtr).nextPtr=DevicePtr;
                  DevicePtr=newDevicePtr;
        printf("Caratteristiche DevicePtr:\n ID : %d\n Nome : %s\n Totale Netto : %f\n Totale : %f\n",(*DevicePtr).ID,(*DevicePtr).nome,(*DevicePtr).TotaleNetto,newDevicePtr->Totale );
                  }
              else{
                   (*newDevicePtr).nextPtr=currentDevicePtr;
                   (*previousDevicePtr).nextPtr=newDevicePtr;
                   printf("cucu3\n");
                   }          
        
        printf("cucu4\n");
    }
    else { printf("Errore, Memoria non disponibile"); }
    }
    
    
    //------------------------------------------------------//
    void salvalista (TipoDispositivo *Dispo) { //*&Device
    
    FILE *ListDevPtr;
    TipoDispositivo *currentPtr;
    
      if (( ListDevPtr = fopen("ListaDispositivi.txt", "wb+")) == NULL){
      	 printf("Il file non può essere aperto");
           }
    	 else{
              if (Dispo !=NULL){
                 currentPtr=Dispo;
                 while((*currentPtr).nextPtr!=NULL){
                    fwrite(&currentPtr,sizeof(TipoDispositivo),1,ListDevPtr);    //&*Dispo=&Device
                    currentPtr=(*currentPtr).nextPtr;
                 }
              }
              else{
                   printf("Lista Dispositivi vuota, impossibile salvare l'elenco dei dispositivi\n");
                   return;
                   }
                 fclose(ListDevPtr);
         }
    }
    //------------------------------------------------------//
    void calcolaconsumo (TipoDispositivo *DevicePtr){                  //*&Device
    
    float QFV = 0.0819672131;
    float QFD = -0.0369603825;
    float QEF1 = 0.09702;
    float QEF2 = 0.08631;
    float DF1 = 0.01154;
    float DF2 = 0.01154;
    float DV = 0;
    float pereq = -0.00065 ;
    float QPOT = 0.0154090164 * 3;
    float QFR = 0.0163934426;
    float QVR = 0;
    float IEC = 0.0227;
    int wattaggio;
    float kwh;
    int anno = 365;
    int oref1;
    int oref2;
    int ore;
    float Totale;
    float TotQFV;
    float TotQF;
    float TotQE;
    float TotQEF1;
    float TotQEF2;
    float TotRete;
    float TotImposte;
    
    printf("Inserisci l'ID del Dispositivo, 0 per tornare al menu\n");
    	       scanf("%d", &(*DevicePtr).ID);
    	       printf ("ID Dispositivo: %d\n", (*DevicePtr).ID);
    printf("Inserisci Il Nome del Dispositivo, 0 per tornare al menu\n");
    	       scanf("%s", (*DevicePtr).nome);
    	       printf ("Nome Dispositivo: %s\n", (*DevicePtr).nome);
    printf("Inserire in Watt il consumo del dispositivo da misurare -1 per uscire \n>");
    scanf("%d", &wattaggio );
    
          printf("Inserire il monte ore in fascia F1 di attività  del dispositivo\n>");
          scanf("%d", &oref1);
          printf("Inserire il monte ore in fascia F2 di attività  del dispositivo\n>");
          scanf("%d", &oref2);
    
          ore = oref1 + oref2;
    
                
          kwh = (float) wattaggio / 1000;
          TotQFV= (QFV + QFD) * anno;
          TotQEF1 = (QEF1+DF1)* kwh * anno * oref1;
          TotQEF2 = (QEF2+DF2)* kwh * anno * oref2;
          TotQE= ((DV + pereq) * kwh * anno * ore) + TotQEF1 + TotQEF2;
          TotRete= (QFR + QVR + QPOT) * anno;
          TotImposte = IEC * anno;
          TotQF= TotQFV + TotRete ; 
          Totale = TotQF + TotQE + TotImposte;
    
                printf( "Ecco quanto consuma il dispositivo annualmente\n\n");
                printf ("Totale Consumo : %f kwh/anno\n", kwh * anno * ore);
                printf("Totale Quota Energia :%f euro/anno\n", TotQE);
                printf("Totale Quota Fissa :%f euro/anno\n", TotQF);
                printf("Totale Imposte :%f euro/anno\n", TotImposte);
                printf("Totale Imposte Rete :%f euro/anno\n", TotRete);
                printf ("Totale imposte comprese : %f euro/anno \n\n" ,Totale);
                
                (*DevicePtr).watt = wattaggio;   //Device.watt ecc
                DevicePtr->Totale = Totale;      //Device.Totale con operatore freccia
                (*DevicePtr).TotaleNetto = Totale - TotImposte;       
                
                printf("Caratteristiche Dispositivo:\n ID : %d\n Nome : %s\n Totale Netto : %f\n Totale : %f\n",(*DevicePtr).ID,(*DevicePtr).nome,(*DevicePtr).TotaleNetto,DevicePtr->Totale );   
    }
    
    Dunque intanto i vari printf ("cucu"), o printf("Caratteristiche Dispositivo") servono per rendermi conto del percorso del flusso di esecuzione e del valore dei dati nella struct che devono rimanere uguali ad ogni ritorno.

    Il Problema è il seguente in main nel case 1 dello switch chiedo ancora una volta a printf di farmi vedere cosa contiene la struct e il programma compila ma mi restituisce un segmentation fault
  • Re: Problema segmentation fault .c

    Il problema è che il puntatore

    DispoPtr

    è NULL. E questo perché, passandolo alla funzione che aggiunge l'elemento, non lo passi per puntatore. Ovvero

    TipoDispositivo **DispoPtr
  • Re: Problema segmentation fault .c

    Aspetta fammi capire.
    Quando invoco nuovodispositivo passando DispoPtr gli sto passando l'indirizzo del puntatore DispoPtr.

    Nella funzione nuovodispositivo utilizzo il puntatore DevicePtr per puntare all'indirizzo di DispoPtr, quindi non dovrei ottenere un puntatore all'indirizzo del puntatore?
  • Re: Problema segmentation fault .c

    Emanuele90 ha scritto:


    Aspetta fammi capire.
    Quando invoco nuovodispositivo passando DispoPtr gli sto passando l'indirizzo del puntatore DispoPtr.
    No, gli stai passando il "valore del puntatore".
    Nella funzione nuovodispositivo utilizzo il puntatore DevicePtr per puntare all'indirizzo di DispoPtr, quindi non dovrei ottenere un puntatore all'indirizzo del puntatore?
    Non hai alcun puntatore a puntatore che è invece quello che ti serve.
Devi accedere o registrarti per scrivere nel forum
29 risposte