[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.
Rispondi
Avatar utente
RedSkull92
Linux 3.x
Linux 3.x
Messaggi: 567
Iscritto il: mar 21 apr 2009, 17:25
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox
Località: Palermo
Contatta:

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

Messaggio da RedSkull92 »

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 15 nov 2010, 21:05, modificato 1 volta in totale.

Avatar utente
Calzo
Linux 1.x
Linux 1.x
Messaggi: 112
Iscritto il: sab 6 ott 2007, 22:21
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE
Località: MN

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

Messaggio da Calzo »

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
RedSkull92
Linux 3.x
Linux 3.x
Messaggi: 567
Iscritto il: mar 21 apr 2009, 17:25
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox
Località: Palermo
Contatta:

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

Messaggio da RedSkull92 »

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 3.x
Linux 3.x
Messaggi: 567
Iscritto il: mar 21 apr 2009, 17:25
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox
Località: Palermo
Contatta:

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

Messaggio da RedSkull92 »

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
Calzo
Linux 1.x
Linux 1.x
Messaggi: 112
Iscritto il: sab 6 ott 2007, 22:21
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE
Località: MN

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

Messaggio da Calzo »

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
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

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

Messaggio da targzeta »

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
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
RedSkull92
Linux 3.x
Linux 3.x
Messaggi: 567
Iscritto il: mar 21 apr 2009, 17:25
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox
Località: Palermo
Contatta:

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

Messaggio da RedSkull92 »

Perfettissimo spina sei stato più che esaustivo, ti ringrazio hai chiarito alcuni miei dubbi, grazie! :D

Rispondi