PDA

Visualizza la versione completa : [C] Errore di segmentazione su accesso a memoria allocata


Enzo93
15-09-2014, 23:35
Salve a tutti, sono alle prime armi col linguaggio C e sto preparando alcuni progetti per l'università.
Il programma non va avanti ed eseguendo un debug ho riscontrato un errore di segmentazione al rigo 42, ho messo una freccetta nel codice per indicarvela.
Nel codice c'è anche scritta la traccia, non è svolta tutta poichè provavo le prime function e mi sono imbattuto in questo errore.

Spero che possiate aiutarmi, grazie anticipatamente. :)



/*Si vuole simulare l’archivio di chiamate di un gestore telefonico. L’archivio risulta
mensile (31 giorni) . Ogni giorno vengono effettuate al massimo 10 chiamate e il
costo al minuto di una chiamata è di 10 centesimi. Ogni chiamata è identificata dal
numero chiamante, il numero ricevente, la durata della chiamata. Provvedere
all’implementazione dell’algoritmo per la simulazione dell’archivio.
Permettere, inoltre, all’utente di:
• Dato un numero telefonico visualizzare tutte le chiamate con le relative
informazioni in un singolo giorno
• Dato un giorno e un numero telefonico visualizzare il costo totale delle
chiamate (usare un algoritmo incrementale ricorsivo).
L’archivio può anche essere inizializzato con informazioni casuali. Effettuare almeno
due test per ognuna delle opzioni dell’utente.*/




#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define chiamate 10
#define giorni 30


char *numeri[]={"3341431454", "3462154556", "3911177368", "3338083794", "3398379801"};


typedef struct{ //Dichiarazione struct con io dati delle chiamate.
char *chiamante;
int ricevente;
int durata;
}Dati;


typedef struct{ //Dichiarazione struct contenente l'archivio mensile.
Dati *elenco[chiamate][giorni];
}Archivio;




Archivio creaDati(){ //Funzione per creare l'archivio, essa restituisce una struct di tipo Archivio.
Archivio archivio;
srand(time(NULL));
int i=0, j=0, k=0;
for (i=0; i<=giorni;){ //Ciclo for per riempire i campi Dati, una rand genera casualmente l'indice j dei numeri,
//una rand genera casualmente numeri che ricevono la chiamata ed un'ultima genera la durata.
for (k=0; k<chiamate; k++){
j=rand()%5;
----> archivio.elenco[k][i]->chiamante = numeri[j];
archivio.elenco[k][i]->ricevente = 1000000+rand()%999999+1;
archivio.elenco[k][i]->durata = rand()%121;
}
}
return archivio;
}


void stampaDati(Archivio archivio){ //Procedura per stampare l'archivio, prende come input una struct di tipo Archivio.
int i=0, k=0;
for (i=0; i<=giorni;){
printf("\n\n\t\t----------[GIORNO %d]----------\n\n CHIAMANTE\t\tRICEVENTE\t\tDURATA", i+1);
for (k=0; k<chiamate; k++){
printf("\n[C.%d] %s\t%d\t\t\t%d\tmin.", k+1, archivio.elenco[k][i]->chiamante, archivio.elenco[k][i]->ricevente, archivio.elenco[k][i]->durata);
}
printf("\n\n\t\tPremi invio per scorrere l'elenco.\n\t\t Premi 'e' per ritornare.\n");
getchar();
if (getchar()=='e')
break;
else
i++;
}
}


void stampaElenco(){ //Procedura per stampare l'elenco dei numeri.
int i=0;
printf("I numeri presenti nel database sono i seguenti:\n");
for (i=0; i<5; i++)
printf("[N%d] (+39)%s\n", i+1, numeri[i]);
getchar();
}


void main(){
Archivio simula; //Dichiaro una variabile di tipo Archivio.
stampaElenco(); //Stampo l'elenco.
simula=creaDati(); //Creo i dati.
stampaDati(simula); //Stampo i dati.
return 0;
}

minomic
16-09-2014, 11:06
Ciao,
i problemi nel codice sono diversi, ma il principale è che non c'è alcuna chiamata alla funzione malloc. Se non allochi la memoria, come puoi poi andarci a scrivere qualcosa? Per forza ti dà l'errore di segmentazione!
Inoltre è sbagliato anche il modo in cui copi le stringhe: non si usa l'operatore = ma la funzione strcpy.

Alex'87
16-09-2014, 12:52
Oltre a quanto detto da minomic, un suggerimento:



Archivio simula; //Dichiaro una variabile di tipo Archivio.
stampaElenco(); //Stampo l'elenco.
simula=creaDati(); //Creo i dati.
stampaDati(simula); //Stampo i dati.


Commenti di questo tipo sono solo inutili, non perderci tempo. Commenta le parti ostiche, non l'ovvio!

Enzo93
16-09-2014, 13:08
Ciao,
i problemi nel codice sono diversi, ma il principale è che non c'è alcuna chiamata alla funzione malloc. Se non allochi la memoria, come puoi poi andarci a scrivere qualcosa? Per forza ti dà l'errore di segmentazione!
Inoltre è sbagliato anche il modo in cui copi le stringhe: non si usa l'operatore = ma la funzione strcpy.
Ciao, grazie per la risposta. Non ho mai usato la chiamata malloc, ho visto un esempio di codice, così può andare bene?


for (i=0; i<=giorni; i++)
for (k=0; k<chiamate; k++)
archivio.elenco[k][i] = (Dati*) malloc ( sizeof(Dati) ) ;



Oltre a quanto detto da minomic, un suggerimento:



Archivio simula; //Dichiaro una variabile di tipo Archivio.
stampaElenco(); //Stampo l'elenco.
simula=creaDati(); //Creo i dati.
stampaDati(simula); //Stampo i dati.


Commenti di questo tipo sono solo inutili, non perderci tempo. Commenta le parti ostiche, non l'ovvio!
Grazie, seguirò il tuo consiglio. :D

minomic
16-09-2014, 13:52
Diciamo che ogni volta che vuoi usare una struct Dati devi allocare il campo "chiamante". Però non mi è molto chiaro il motivo per cui, in Archivio, fai


Dati *elenco[chiamate][giorni];


Sarebbe un puntatore a un array bi-dimensionale? Secondo me volevi solo una matrice, nel qual caso togli l'asterisco.

Enzo93
16-09-2014, 16:11
Diciamo che ogni volta che vuoi usare una struct Dati devi allocare il campo "chiamante". Però non mi è molto chiaro il motivo per cui, in Archivio, fai


Dati *elenco[chiamate][giorni];

Sarebbe un puntatore a un array bi-dimensionale? Secondo me volevi solo una matrice, nel qual caso togli l'asterisco.

In pratica volevo creare un elenco di 31 giorni in cui in ogni giorno vi sono 10 telefonate, in questo modo per gli altri punti del problema posso scegliere giorno e numero da input e stampare le informazioni che mi servono.

Per quanto riguarda il codice, l'ho modificato in questo modo (ho riportato solo la funzione interessata):

Archivio creaDati(){ //Funzione per creare l'archivio, essa restituisce una struct di tipo Archivio. int i=0, j=0, k=0;
Archivio archivio;
for (i=0; i<=giorni; i++)
for (k=0; k<chiamate; k++)
archivio.elenco[k][i].chiamante=malloc(sizeof(Dati));
srand(time(NULL));
for (i=0; i<=giorni;){ //Ciclo for per riempire i campi Dati, una rand genera casualmente l'indice j dei numeri,
//una rand genera casualmente numeri che ricevono la chiamata ed un'ultima genera la durata.
for (k=0; k<chiamate; k++){
j=rand()%5;
strcpy(archivio.elenco[k][i].chiamante, numeri[j]);
archivio.elenco[k][i].ricevente = 1000000+rand()%999999+1;
archivio.elenco[k][i].durata = rand()%121;
}
}
return archivio;
}

Ora il programma non va in crash ma mi esegue solo la prima procedura per la stampa dell'elenco e non esegue altro... :confused:

minomic
16-09-2014, 18:16
Prova a postare il codice completo nella sua ultima versione, così gli diamo un'occhiata.

Enzo93
16-09-2014, 18:34
Eccolo...

/*Si vuole simulare l’archivio di chiamate di un gestore telefonico. L’archivio risultamensile (31 giorni) . Ogni giorno vengono effettuate al massimo 10 chiamate e il
costo al minuto di una chiamata è di 10 centesimi. Ogni chiamata è identificata dal
numero chiamante, il numero ricevente, la durata della chiamata. Provvedere
all’implementazione dell’algoritmo per la simulazione dell’archivio.
Permettere, inoltre, all’utente di:
• Dato un numero telefonico visualizzare tutte le chiamate con le relative
informazioni in un singolo giorno
• Dato un giorno e un numero telefonico visualizzare il costo totale delle
chiamate (usare un algoritmo incrementale ricorsivo).
L’archivio può anche essere inizializzato con informazioni casuali. Effettuare almeno
due test per ognuna delle opzioni dell’utente.*/




#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define chiamate 10
#define giorni 30


char *numeri[]={"3341431454", "3462154556", "3911177368", "3338083794", "3398379801"};


typedef struct{ //Dichiarazione struct con io dati delle chiamate.
char *chiamante;
int ricevente;
int durata;
}Dati;


typedef struct{ //Dichiarazione struct contenente l'archivio mensile.
Dati elenco[chiamate][giorni];
}Archivio;




Archivio creaDati(){ //Funzione per creare l'archivio, essa restituisce una struct di tipo Archivio.
int i=0, j=0, k=0;
Archivio archivio;
for (i=0; i<=giorni; i++)
for (k=0; k<chiamate; k++)
archivio.elenco[k][i].chiamante=malloc(sizeof(Dati));
srand(time(NULL));
for (i=0; i<=giorni;){ //Ciclo for per riempire i campi Dati, una rand genera casualmente l'indice j dei numeri,
//una rand genera casualmente numeri che ricevono la chiamata ed un'ultima genera la durata.
for (k=0; k<chiamate; k++){
j=rand()%5;
strcpy(archivio.elenco[k][i].chiamante, numeri[j]);
archivio.elenco[k][i].ricevente = 1000000+rand()%999999+1;
archivio.elenco[k][i].durata = rand()%121;
}
}
return archivio;
}


void stampaDati(Archivio archivio){ //Procedura per stampare l'archivio, prende come input una struct di tipo Archivio.
int i=0, k=0;
for (i=0; i<=giorni;){
printf("\n\n\t\t----------[GIORNO %d]----------\n\n CHIAMANTE\t\tRICEVENTE\t\tDURATA", i+1);
for (k=0; k<chiamate; k++){
printf("\n[C.%d] %s\t%d\t\t\t%d\tmin.", k+1, archivio.elenco[k][i].chiamante, archivio.elenco[k][i].ricevente, archivio.elenco[k][i].durata);
}
printf("\n\n\t\tPremi invio per scorrere l'elenco.\n\t\t Premi 'e' per ritornare.\n");
getchar();
if (getchar()=='e')
break;
else
i++;
}
}


void stampaElenco(){ //Procedura per stampare l'elenco dei numeri.
int i=0;
printf("I numeri presenti nel database sono i seguenti:\n");
for (i=0; i<5; i++)
printf("[N%d] (+39)%s\n", i+1, numeri[i]);
getchar();
}


void main(){
Archivio simula;
stampaElenco();
simula=creaDati();
stampaDati(simula);
return 0;
}

Grazie ancora per l'aiuto...

minomic
16-09-2014, 18:49
Così funziona:



#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define chiamate 10
#define giorni 30




char *numeri[]= {"3341431454", "3462154556", "3911177368", "3338083794", "3398379801"};




typedef struct //Dichiarazione struct con io dati delle chiamate.
{
char *chiamante;
int ricevente;
int durata;
} Dati;




typedef struct //Dichiarazione struct contenente l'archivio mensile.
{
Dati elenco[chiamate][giorni];
} Archivio;








Archivio creaDati() //Funzione per creare l'archivio, essa restituisce una struct di tipo Archivio.
{
int i=0, j=0, k=0;
Archivio archivio;


for (i=0; i<giorni; i++)
{
for (k=0; k<chiamate; k++)
{
archivio.elenco[k][i].chiamante=malloc(sizeof(Dati));
j=rand()%5;
strcpy(archivio.elenco[k][i].chiamante, numeri[j]);
archivio.elenco[k][i].ricevente = 1000000+rand()%999999+1;
archivio.elenco[k][i].durata = rand()%121;
}
}
return archivio;
}




void stampaDati(Archivio archivio) //Procedura per stampare l'archivio, prende come input una struct di tipo Archivio.
{
int i=0, k=0;
for (i=0; i<=giorni;)
{
printf("\n\n\t\t----------[GIORNO %d]----------\n\n CHIAMANTE\t\tRICEVENTE\t\tDURATA", i+1);
for (k=0; k<chiamate; k++)
{
printf("\n[C.%d] %s\t%d\t\t\t%d\tmin.", k+1, archivio.elenco[k][i].chiamante, archivio.elenco[k][i].ricevente, archivio.elenco[k][i].durata);
}
printf("\n\n\t\tPremi invio per scorrere l'elenco.\n\t\t Premi 'e' per ritornare.\n");
getchar();
if (getchar()=='e')
break;
else
i++;
}
}




void stampaElenco() //Procedura per stampare l'elenco dei numeri.
{
int i=0;
printf("I numeri presenti nel database sono i seguenti:\n");
for (i=0; i<5; i++)
printf("[N%d] (+39)%s\n", i+1, numeri[i]);
getchar();
}




int main()
{
srand(time(NULL));


Archivio simula;
stampaElenco();
simula = creaDati();
stampaDati(simula);
return 0;
}



C'è ancora qualcosa di sbagliato (secondo me) nel fatto che premendo 'e' non esce, comunque dovresti riuscire a sistemare facilmente.
Il problema era nel ciclo for: avevi messo i<=giorni mentre deve essere i<giorni. Ricordati che si va da 0 a (giorni-1).
E poi c'erano due doppi cicli for, mentre uno è sufficiente.

oregon
16-09-2014, 18:56
Così funziona:

Ma questo

archivio.elenco[k][i].chiamante=malloc(sizeof(Dati));



non ha molto senso ...

Loading