|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Junior Member
Iscritto dal: Nov 2010
Messaggi: 5
|
[C] Segmentation Fault in un char*
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: Codice:
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) Codice:
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 |
|
|
|
|
|
#2 |
|
Member
Iscritto dal: Aug 2005
Messaggi: 168
|
Il malloc di users[last].password è commentato, era una prova?
|
|
|
|
|
|
#3 |
|
Junior Member
Iscritto dal: Nov 2010
Messaggi: 5
|
|
|
|
|
|
|
#4 | |
|
Junior Member
Iscritto dal: Nov 2010
Messaggi: 5
|
Quote:
Main.c http://pastebin.com/KP0Zf0UC Lib.c http://pastebin.com/1T4zi7he |
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Feb 2006
Città: Parma
Messaggi: 3010
|
Non mi pare che tu stia trattando correttamente gli array di char.
Dal codice in questo thread: Codice:
users[last].username=malloc(BUFSIZ);
/*users[last].password=malloc(BUFSIZ);*/
users[last].username=username;
Nel pastebin: Codice:
fwrite(&users[i],sizeof(user),1,fp); [...] fread(&users[i],sizeof(user),1,fp2); 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? Se vuoi mantenere i puntatori nelle 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.
__________________
~Breve riferimento ai comandi GNU/Linux (ormai non molto breve...) |
|
|
|
|
|
#6 | |||
|
Junior Member
Iscritto dal: Nov 2010
Messaggi: 5
|
Quote:
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 Quote:
sarebbe meglio cambiare Codice:
fwrite(&users[i],sizeof(user),1,fp); Codice:
fwrite(users[i],sizeof(user),1,fp); Anche qui, suggerimenti sono benvenuti! Quote:
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! |
|||
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Feb 2006
Città: Parma
Messaggi: 3010
|
Sono un po' arrugginito in C liscio, ma mi riferivo a questo:
Codice:
strncpy( users[last].username, username, BUFSIZ ); Codice:
typedef struct userData{
char username[USR_SIZE];
char password[PWD_SIZE];
long int nMessages;
long int bytes_quota;
message *msgs;
}user;
Codice:
fwrite(&users[i],sizeof(user),1,fp); [...] fread(&users[i],sizeof(user),1,fp2); Oppure questo Codice:
typedef struct userData{
char *username;
char *password;
long int nMessages;
long int bytes_quota;
message *msgs;
}user;
Codice:
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 );
__________________
~Breve riferimento ai comandi GNU/Linux (ormai non molto breve...) |
|
|
|
|
|
#8 | |
|
Junior Member
Iscritto dal: Nov 2010
Messaggi: 5
|
Quote:
Ok.. allora avevo capito bene! ..ho modificato or ora e...funziona! Aspetta che posto i source.. Main.c http://pastebin.com/pYdupwXh Lib.c http://pastebin.com/P4zRE5Ug |
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Feb 2006
Città: Parma
Messaggi: 3010
|
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.
__________________
~Breve riferimento ai comandi GNU/Linux (ormai non molto breve...) |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 10:18.




















