Repository 32bit  Forum
Repository 64bit  Wiki

[RISOLTO]Segmentation Fault o errori di allocazione. [C]

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

[RISOLTO]Segmentation Fault o errori di allocazione. [C]

Messaggioda RedSkull92 » dom nov 14, 2010 16:56

Il mio professore d'informatica ci ha detto di realizzare un programma per la gestione di una catena di alberghi utilizzando l'allocazione dinamica.
Il primo inserimento va a buon fine, il secondo pure ma vengono immessi valori "sballati", per il terzo crasha direttamente tutto...
Il sorgente a me sembra corretto (non da errori in fase di compilazione)

Mi date una mano a capire perché ?
Grazie.
Il sorgente è quì: http://sprunge.us/PShP?c
Ultima modifica di RedSkull92 il lun nov 15, 2010 21:05, modificato 1 volta in totale.
Avatar utente
RedSkull92
Linux 2.6
Linux 2.6
 
Messaggi: 553
Iscritto il: mar apr 21, 2009 16:25
Località: Palermo
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox

Re: Segmentation Fault o errori di allocazione. [C]

Messaggioda Calzo » dom nov 14, 2010 18:18

Devi modificare la funzione carica. Io l'ho definita in modo che restituisca un puntatore ad ALBERGHI e così funziona:
Codice: Seleziona tutto
ALBERGHI *carica(ALBERGHI *catena,int *numero)
{
    ALBERGHI *temp;
   
    //Se non e' il primo inserimento realloca la memoria.
    if(*numero > 0)
    {
        temp = (ALBERGHI*)realloc(catena,(*numero+1)*sizeof(ALBERGHI));
        if (temp != NULL)
            catena = temp;
        else
            exit(1);
    }
    //Inserimento dati albergo.
    printf("\n- INSERIMENTO ALBERGO -\nInserisci codice albergo: ");
    scanf("%d",&(catena+(*numero))->codice_h);
    printf("Inserisci nome: ");
    scanf("%s",(catena+(*numero))->nome);
    printf("Inserisci Localita': ");
    scanf("%s",(catena+(*numero))->luogo);
    printf("Inserisci numero stelle: ");
    scanf("%d",&(catena+(*numero))->n_stelle);
    printf("Inserisci numero di stanze: ");
    scanf("%d",&(catena+(*numero))->n_stanze);
    //Funzione per inserire le stanze.
    ins_s(catena,*numero,(catena+(*numero))->n_stanze);
    (*numero)++;
    printf("Albergo inserito correttamente!\n");
    return catena;
}

ovviamente quando fai il case iniziale, lo dovrai modificare in modo da salvare nuovamente la variabile catena:
Codice: Seleziona tutto
[...]
switch(scelta)
        {
            case 1:
                catena = carica(catena,&numero);
                break;
            case 2:
                h_info(catena,numero);
                break;
            case 3:
                s_info(catena,numero);
                break;
            case 4:
                free_places(catena,numero);
                break;
            case 5:
                s_all(catena,numero);
                break;
            default:
                break;
        }
[...]

bye
EDIT: io ho provato solo ad aggiungere e stampare (funzione 1 e 5). Le altre funzioni non le ho provate.
Avatar utente
Calzo
Linux 2.0
Linux 2.0
 
Messaggi: 112
Iscritto il: sab ott 06, 2007 21:21
Località: MN
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE

Re: Segmentation Fault o errori di allocazione. [C]

Messaggioda RedSkull92 » dom nov 14, 2010 19:14

Il codice funziona solo per il 1° albergo inserito, se io dopo aver inserito l'albergo (dal menù scelta 1) ne voglio inserire un'altro me lo permette però una volta finito l'inserimento e voglio stampare i valori la funzione s_all mi stampa correttamente SOLO il 1° albergo e non il 2° andando in segmentation fault alla fine, quale potrebbe essere il problema ?
Avatar utente
RedSkull92
Linux 2.6
Linux 2.6
 
Messaggi: 553
Iscritto il: mar apr 21, 2009 16:25
Località: Palermo
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox

Re: Segmentation Fault o errori di allocazione. [C]

Messaggioda RedSkull92 » dom nov 14, 2010 20:15

Ce l'ho fatta!
http://sprunge.us/gfcM?c
Ora una curiosità, come mai se la funzione è dichiarata come void non funziona ?
Cioè modifanco la funzione e mettendo catena = carica.... tutto funziona mentre se metto la funzione come void e carica(....) non funziona.
Non dovrebbe essere la stessa cosa ?
(Passo per riferifmento catena e modifico man mano i campi)
Grazie per le delucidazioni.
Avatar utente
RedSkull92
Linux 2.6
Linux 2.6
 
Messaggi: 553
Iscritto il: mar apr 21, 2009 16:25
Località: Palermo
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox

Re: Segmentation Fault o errori di allocazione. [C]

Messaggioda Calzo » dom nov 14, 2010 21:21

RedSkull92 ha scritto:Cioè modifanco la funzione e mettendo catena = carica.... tutto funziona mentre se metto la funzione come void e carica(....) non funziona.
Non dovrebbe essere la stessa cosa ?

Me lo sono chiesto anche io: dovrebbe essere la stessa cosa... ma non lo è perchè cambia l'indirizzo di memoria a cui la variabile catena stà puntando.
Se metti una printf(%X - %X, temp, catena) subito dopo l'assegnazione della variabile temp nella funzione carica() e anche prima e dopo la chiamata a carica(), vedi che il puntatore cambia nella funzione, ma non cambia prima e dopo la chiamata. A questo punto se semplicemente eguagli catena e temp vai solo a modificare il puntatore salvato nello stack, ma non la vera variabile... almeno questo è quello che penso.

bye
Avatar utente
Calzo
Linux 2.0
Linux 2.0
 
Messaggi: 112
Iscritto il: sab ott 06, 2007 21:21
Località: MN
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE

Re: Segmentation Fault o errori di allocazione. [C]

Messaggioda targzeta » dom nov 14, 2010 21:23

Il motivo è che in C i parametri sono passati per copia e non per valore. Quando tu allochi un nuovo albergo esegui una realloc() la cui memoria la assegni alla variabile locale 'catena', quindi la variabile locale punta correttamente alla nuova locazione mentre la variabile 'catena' del main() continua a puntare alla sua vecchia locazione. Spero di essermi spiegato bene.

Alcune note:
  • Il prototipo della funzione ins_s() non mi piace. Il numero di stanze è già scritto nell'hotel. Inoltre non dovrebbe prendere l'array ma l'hotel specifico. Ancora, allochi sempre una stanza in più. Ecco come l'ho modificata
    Codice: Seleziona tutto
    void ins_s(ALBERGHI *hotel)
    {
      int i;

      if ( (hotel->stanza = (STANZE*)malloc((hotel->n_stanze)*sizeof(STANZE))) == NULL )
        {
          printf("Impossibile inserire stanze.\n");
          exit(1);
        }

      printf("\n- INSERIMENTO STANZA -");
      for(i=0; i < hotel->n_stanze; i++)
        {
          printf("\nInserisci numero stanza %d: ",i+1);
          scanf("%d",&hotel->stanza[i].n_stanza);
          printf("Inserisci numero posti letto: ");
          scanf("%d",&hotel->stanza[i].np_letto);
          printf("Inserisci se la stanza e' libera (0=libera, 1=occupata): ");
          scanf("%d",&hotel->stanza[i].stato);
        }
      printf("Stanze inserite correttamente!\n\n");
      return;
    }
  • Anche gli alberghi, ne allochi sempre uno in più, poi lavori sul precedente. La malloc iniziale è inutile: se non hai alberghi è inutile allocarne uno. Io ho fatto così:
    Codice: Seleziona tutto
    int main()
    {
      ALBERGHI *catena = NULL;
      int scelta,numero=0;

      do
        {
          printf("\n- MENU -\n"
    ...
    e poi la funzione carica()(nota anche che la variabile temp è inutile):
    Codice: Seleziona tutto
    ALBERGHI *carica(ALBERGHI *catena, int *numero)
    {
      if ( (catena = (ALBERGHI*)realloc(catena,((*numero)+1)*sizeof(ALBERGHI))) == NULL )
        exit(1);

      printf("\n- INSERIMENTO ALBERGO -\nInserisci codice albergo: ");
      scanf("%d",&(catena+(*numero))->codice_h);
      printf("Inserisci nome: ");
      scanf("%s",(catena+(*numero))->nome);
      printf("Inserisci Localita': ");
      scanf("%s",(catena+(*numero))->luogo);
      printf("Inserisci numero stelle: ");
      scanf("%d",&(catena+(*numero))->n_stelle);
      printf("Inserisci numero di stanze: ");
      scanf("%d",&(catena+(*numero))->n_stanze);
      /*Funzione per inserire le stanze.*/
      ins_s(catena+(*numero));;
      (*numero)++;
      printf("Albergo inserito correttamente!\n");
      return catena;
    }
    Vedi il man della realloc(). Se la variabile è NULL si comporta come la malloc().

Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6168
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: Segmentation Fault o errori di allocazione. [C]

Messaggioda RedSkull92 » lun nov 15, 2010 21:03

Perfettissimo spina sei stato più che esaustivo, ti ringrazio hai chiarito alcuni miei dubbi, grazie! :D
Avatar utente
RedSkull92
Linux 2.6
Linux 2.6
 
Messaggi: 553
Iscritto il: mar apr 21, 2009 16:25
Località: Palermo
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite

cron