View Full Version : [C] Segmentation Fault in un char*
InfinitiOltre
18-04-2011, 18:52
Ciao a tutti,
scrivo qui dopo 3 giorni che guardo e riguardo (anche in sogno, purtroppo..) il codice alla ricerca del bug..
Praticamente il problema è questo:
1) faccio una malloc di un tot di grandezza ad un char *
2) con la scanf prendo l'input
3) stampo l'input preso
4) segmentation fault.
Vi posto il codice, almeno capite meglio..
Strutture coinvolte:
typedef struct msg{
char *destination;
char *subject;
char *text;
}message;
/* User Data.
* It contains all data stored of an user.
*/
typedef struct userData{
char *username;
char *password;
long int nMessages;
long int bytes_quota;
message *msgs;
}user;
Funzione 'addUser' (la funzione che mi fa rimanere insonne..)
DEFAULT_QUOTA_SIZ = 1048576 (..che è uguale a 1024*1024 che è il numero di byte che formano un megabyte)
int addUser(char *username, user *users, int nAccounts){
char *path;
FILE *fp;
int i,last;
last=nAccounts-1;
users[last].username=malloc(BUFSIZ);
/*users[last].password=malloc(BUFSIZ);*/
users[last].username=username;
printf(" ___ADD_USER___\n");
for(i=0;i<(nAccounts);i++){
printf("username: %s\npassword: %s\nbytes_quota: %ld\nnMessages: %ld\n", users[i].username, users[i].password, users[i].bytes_quota, users[i].nMessages);
}
/*** BEGIN OF PROBLEMS ***/
printf("Insert a password for the '%s' account: \n",users[last].username);
scanf("%s",users[last].password);
for(i=0;i<nAccounts;i++){
printf("username: %s\npassword: %s\nbytes_quota: %ld\nnMessages: %ld\n", users[i].username, users[i].password, users[i].bytes_quota, users[i].nMessages);
}
printf("non arrivo qui-");
users[last].bytes_quota=DEFAULT_QUOTA_SIZ; /* default quota: 1MB */
printf("non arrivo qui-");
/*** END OF PROBLEMS ***/
path="dir/";
/* Creating user mailbox file */
sprintf(path,"%s",username);
fp=fopen(path, "w");
if(fp==NULL){
perror("user file creation");
return EXIT_FAILURE;
}
fwrite(&users[last],sizeof(user),1,fp);
fclose(fp);
/* Updating 'usrs' file with the new user */
fp=fopen("dir/usrs", "a");
if(fp==NULL){
perror("user file creation");
return EXIT_FAILURE;
}
fprintf(fp,"%s",username);
fclose(fp);
return EXIT_SUCCESS;
}
Per maggior chiarezza ho messo i file su pastebin.com..
Ecco i link:
Main.c
http://pastebin.com/E0nXKFwp
Lib.c
http://pastebin.com/STTQq80B
Il malloc di users[last].password è commentato, era una prova?
InfinitiOltre
18-04-2011, 19:24
Il malloc di users[last].password è commentato, era una prova?
Si..
Comunque, ho riprovato per sicurezza e, con o senza la malloc è lo stesso risultato: SEGMENTATION FAULT.
:'(
qualche altro consiglio?
InfinitiOltre
18-04-2011, 19:36
Si..
Comunque, ho riprovato per sicurezza e, con o senza la malloc è lo stesso risultato: SEGMENTATION FAULT.
:'(
qualche altro consiglio?
Aggiornamento dei file sorgenti
Main.c
http://pastebin.com/KP0Zf0UC
Lib.c
http://pastebin.com/1T4zi7he
Gimli[2BV!2B]
18-04-2011, 20:04
Non mi pare che tu stia trattando correttamente gli array di char.
Dal codice in questo thread: users[last].username=malloc(BUFSIZ);
/*users[last].password=malloc(BUFSIZ);*/
users[last].username=username;Prima lo allochi, poi sovrascrivi il puntatore con l'array passato per argomento: memory leak + chissà cosa succederà più avanti.
Nel pastebin:fwrite(&users,sizeof(user),1,fp);
[...]
fread(&users[i],sizeof(user),1,fp2);Scrivi ed ingurgiti l'intera struttura su/da file, paro paro?
Le strutture user contengono solo i puntatori alle stringhe, quindi finiranno per puntare a zone di memoria risalenti ad una precedente esecuzione. Quasi certamente non saranno accessibili, tanto meno sensate. Non credo vedrai le stringhe nel file.
strcpy (http://www.manpagez.com/man/3/strcpy/)?
Se vuoi mantenere i puntatori nelle [I]userData dovresti rivedere il formato del file. Personalmente, nei rari casi in cui mi è stato necessario, mi sono accontentato di scrivere la lunghezza della stringa seguita dal contenuto.
Oppure potresti rendere fisse le dimensioni degli array di char ed alleggerire malloc e complessità aggiuntiva, tanto allochi tutte le stringhe con dimensioni fisse.
InfinitiOltre
18-04-2011, 21:40
;34969137']Non mi pare che tu stia trattando correttamente gli array di char.
Dal codice in questo thread: users[last].username=malloc(BUFSIZ);
/*users[last].password=malloc(BUFSIZ);*/
users[last].username=username;Prima lo allochi, poi sovrascrivi il puntatore con l'array passato per argomento: memory leak + chissà cosa succederà più avanti.
users[last].username=username
viene fatto perchè nell'array di strutture 'users' devo mantenere tutti gli utenti con i loro username, le loro password, ecc..
ecco perchè c'è questo memory leak..
Se, però, hai qualche suggerimento per evitarlo..ben venga :D
Nel pastebin:fwrite(&users[i],sizeof(user),1,fp);
[...]
fread(&users[i],sizeof(user),1,fp2);Scrivi ed ingurgiti l'intera struttura su/da file, paro paro?
Le strutture user contengono solo i puntatori alle stringhe, quindi finiranno per puntare a zone di memoria risalenti ad una precedente esecuzione. Quasi certamente non saranno accessibili, tanto meno sensate. Non credo vedrai le stringhe nel file.
Volevo usare dei file binari..
sarebbe meglio cambiare
fwrite(&users,sizeof(user),1,fp); in fwrite(users[i],sizeof(user),1,fp); ? Perchè, effettivamente, con '&', gli sto passando l'indirizzo, mentre senza gli passo l'intera struttura, così che con l'fread me la leggo successivamente..
Anche qui, suggerimenti sono benvenuti! :D
Se vuoi mantenere i puntatori nelle [I]userData dovresti rivedere il formato del file. Personalmente, nei rari casi in cui mi è stato necessario, mi sono accontentato di scrivere la lunghezza della stringa seguita dal contenuto.
Oppure potresti rendere fisse le dimensioni degli array di char ed alleggerire malloc e complessità aggiuntiva, tanto allochi tutte le stringhe con dimensioni fisse.
Come ho scritto poco sopra, volevo usare dei file binari, perchè a quanto ho capito riescono a memorizzare intere strutture senza farmi impazzire nello scrivere il file .. almeno, questo è quello che ho capito..
Anche qui, come sempre, suggerimenti, sono ben accetti..
Ah, una cosa microscopica, per quanto riguarda il codice in se che mi dici? Leggibilità? Stile? Consigli su come migliorare?
Spero risponderai.. Grazie mille! :D
Gimli[2BV!2B]
18-04-2011, 22:05
Sono un po' arrugginito in C liscio, ma mi riferivo a questo:strncpy( users[last].username, username, BUFSIZ );
E questo:typedef struct userData{
char username[USR_SIZE];
char password[PWD_SIZE];
long int nMessages;
long int bytes_quota;
message *msgs;
}user;accoppiato afwrite(&users[i],sizeof(user),1,fp);
[...]
fread(&users[i],sizeof(user),1,fp2);
****************************************
Oppure questotypedef struct userData{
char *username;
char *password;
long int nMessages;
long int bytes_quota;
message *msgs;
}user;accoppiato ad una roba di questo tipo:size_t sz = strlen( users[i].username );
fwrite( (const void*)&sz, sizeof(size_t),1,fp);
fwrite( (const void*)&users[i].username, sizeof(char), sz, fp );
[...]
size_t sz = NULL;
fread( (void*)&sz, sizeof(size_t), 1, fp );
if( sz > BUFSIZ )
{
//Troppo grande! File danneggiato? Errore?
return;
}
users[i].username = (char*)malloc( sizeof(char) * BUFSIZ );
fread( (void*)&users[i].username, sizeof(char), sz, fp );
InfinitiOltre
19-04-2011, 06:10
;34970160']Sono un po' arrugginito in C liscio, ma mi riferivo a questo:strncpy( users[last].username, username, BUFSIZ );
E questo:typedef struct userData{
char username[USR_SIZE];
char password[PWD_SIZE];
long int nMessages;
long int bytes_quota;
message *msgs;
}user;accoppiato afwrite(&users[i],sizeof(user),1,fp);
[...]
fread(&users[i],sizeof(user),1,fp2);
****************************************
Oppure questotypedef struct userData{
char *username;
char *password;
long int nMessages;
long int bytes_quota;
message *msgs;
}user;accoppiato ad una roba di questo tipo:size_t sz = strlen( users[i].username );
fwrite( (const void*)&sz, sizeof(size_t),1,fp);
fwrite( (const void*)&users[i].username, sizeof(char), sz, fp );
[...]
size_t sz = NULL;
fread( (void*)&sz, sizeof(size_t), 1, fp );
if( sz > BUFSIZ )
{
//Troppo grande! File danneggiato? Errore?
return;
}
users[i].username = (char*)malloc( sizeof(char) * BUFSIZ );
fread( (void*)&users[i].username, sizeof(char), sz, fp );
Ok.. allora avevo capito bene! ..ho modificato or ora e...funziona! :D
Aspetta che posto i source..
Main.c
http://pastebin.com/pYdupwXh
Lib.c
http://pastebin.com/P4zRE5Ug
Gimli[2BV!2B]
19-04-2011, 19:46
Attenzione, nelle strutture user resta sempre il puntatore a message, vale lo stesso ragionamento dei puntatori alle stringhe.
Però vedo che ora i msg non sono molto utilizzati, quindi il problema non si manifesta ma è lì in agguato.
Riguardo all'aspetto del codice direi che è ordinato e contiene commenti in quantità che considero corretta.
Per finire sullo stile ho un'appunto: io spezzerei il main in più funzioni (per esempio il contenuto dell'if(flag) ).
In questo caso non serve a rimuovere codice ripetitivo, ma a renderlo più interpretabile.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.