Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Problema con stringa dinamica!
Forum - C/C++ - Problema con stringa dinamica!

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
mark22 (Normal User)
Newbie


Messaggi: 11
Iscritto: 29/10/2017

Segnala al moderatore
Postato alle 21:54
Domenica, 29/10/2017
Buonasera a tutti.
Sto creando un programmino in C che cifra un qualsiasi file (aprendolo in binario fread,fwrite) passato da riga di comando.
Il programma: nel main si preoccupa di creare una stringa dinamica e, passandola a una funziona chiama apriFile verrà compilata(a blocchi di 255 byte) facendo trovare nella stringa passata dal chiamante il possibile file sempre in binario. Dopo di che verrà sottoposta a algoritmi di cifratura, ma il problema sta proprio in questa prima funzione.Ecco il codice:  
Codice sorgente - presumibilmente C++

  1. void apriFile(char *nomeFile, char **s, int *dim){ //s= stringa da cod/decod, *dim dimensioni della stringa da cod/decod
  2.         FILE *f;  char string[BYTEREAD+1],*aus; //BYTEREAD=255
  3.         int count=0;
  4.         *dim=0;
  5.         f=fopen(nomeFile,"rb");
  6.         if(f==NULL)
  7.                 printf("\nErrore nell'apertura del file.");
  8.         if(*s!=NULL)
  9.                 free(*s);
  10.         *s=(char*)calloc(1,sizeof(char));
  11.         if(*s==NULL){
  12.                 printf("ERRORE!");
  13.                 return;
  14.         }
  15.         while(!feof(f)){
  16.                 inizializzaStringa(string,BYTEREAD+1);
  17.                 count = fread(string,sizeof(char),BYTEREAD,f);
  18.                 (*dim)+=count;
  19.                 aus=(char*)realloc(*s,sizeof(char)*(*dim)); //CRASHA QUA! al secondo giro sempre
  20.                 if(aus==NULL)
  21.                         break;
  22.                 else{
  23.                         *s=aus;
  24.                         strcat(*s,string);
  25.                 }
  26.         }
  27.         fclose(f);
  28. }


Main:
Codice sorgente - presumibilmente C/C++

  1. int main(int argc,char* argv[]){
  2.         char* stringone=NULL;
  3.         int dim;
  4.         if(strcasecmp(argv[1],"/c")==0 || strcasecmp(argv[1],"/d")==0){
  5.                 if(strcasecmp(argv[1],"/c")==0){ //codifica
  6.                         apriFile(argv[2],&stringone,&dim);
  7.                         codifica(argv[2],stringone,argv[3],dim);
  8.                         printf("File criptato correttamente!");
  9.                 }
  10.                 else{ //decodifica
  11.                
  12.                 }
  13.         }
  14.         else{
  15.                 printf("CRYPTO: opzione non valida.");
  16.         }
  17.         free(stringone);
  18.         return 0;
  19. }


dopo veramente tantissime prove e cambio di istruzioni, sono arrivato a capire che il problema è dato da uno '/0' posto  a fine stringa che mi fa crashare il programma quando eseguo la realloc nella funzione..
Il compilatore dice che c'è un problema di SIGTRAP
Vi ringrazio in anticipo :)

Ultima modifica effettuata da mark22 il 30/10/2017 alle 11:03
PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 22:47
Domenica, 29/10/2017
Ho dato una letta molto veloce ma mi sembra che non tieni conto del terminatore quando incrementi *dim di count, forse dovrebbe essere *dim += count+1;

Per completezza puoi mettere anche il codice di inizializzaStringa?

P.S. Non è il compilatore che dà SIGTRAP, ma il sistema operativo quando esegue il tuo programma.

Ultima modifica effettuata da lumo il 29/10/2017 alle 22:48
PM Quote
Avatar
Mikelius (Member)
Expert


Messaggi: 525
Iscritto: 14/04/2017

Segnala al moderatore
Postato alle 1:05
Lunedì, 30/10/2017
Se puoi, passa tutte le funzioni, anche

Codice sorgente - presumibilmente Plain Text

  1. codifica(argv[2],stringone,argv[3],dim)



Ho trovato un errore che non dipende dalle stringhe:

riga 17 del main()

Codice sorgente - presumibilmente Plain Text

  1. free(stringone);



Che succede se il primo if non viene eseguito?

Pr la realloc, prova a utilizzarla con aus, previa allocazione,  e poi a COPIARE aus in *s non a fare coincidere i valori.
Codice sorgente - presumibilmente Plain Text

  1. aus = calloc(1, sizeof(char));
  2. .........
  3. .........
  4. .........
  5. aus = realloc(aus, sizeof(char)*(*dim+1));
  6. ----------------^------------------------------
  7. .......
  8. ......
  9.      strcpy( *s, aus);





PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6384
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 8:37
Lunedì, 30/10/2017
Ma se lavori con file in binario perché usi stringhe e funzioni stringa?

Si usano dei buffer senza terminazione dato che puoi leggere anche byte a zero dal file, infatti usi la fread !
Quindi niente strcpy, strcat ... e simili.

E non usare feof in quel modo, anzi, non usarlo proprio ... è un errore comune tra i principianti

Ultima modifica effettuata da nessuno il 30/10/2017 alle 9:15


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
mark22 (Normal User)
Newbie


Messaggi: 11
Iscritto: 29/10/2017

Segnala al moderatore
Postato alle 14:53
Lunedì, 30/10/2017
Testo quotato

Postato originariamente da lumo:

Ho dato una letta molto veloce ma mi sembra che non tieni conto del terminatore quando incrementi *dim di count, forse dovrebbe essere *dim += count+1;

Per completezza puoi mettere anche il codice di inizializzaStringa?

P.S. Non è il compilatore che dà SIGTRAP, ma il sistema operativo quando esegue il tuo programma.



Correggendo questo il programma funziona correttamente.. grazie
Codice sorgente - presumibilmente C/C++

  1. void inizializzaStringa(char *s,int dim){
  2.         int i;
  3.         for(i=0;i<dim;i++)
  4.                         *(s+i)='\0';
  5. }


Mikelius la funzione codifica non crea nessun problema per adesso, grazie per avermi fatto notare la free(stringone) che porta a un crash se non venisse eseguito il primo if.

Testo quotato

Postato originariamente da nessuno:
Ma se lavori con file in binario perché usi stringhe e funzioni stringa?

Si usano dei buffer senza terminazione dato che puoi leggere anche byte a zero dal file, infatti usi la fread !
Quindi niente strcpy, strcat ... e simili.

E non usare feof in quel modo, anzi, non usarlo proprio ... è un errore comune tra i principianti


Si giusto mi era sfuggito questo particolare.. ho corretto il codice utilizzando fseek e ftell al posto di feof e risulta molto più veloce che leggere il file a blocchi. Ecco il codice:
Codice sorgente - presumibilmente C++

  1. void apriFile(char *nomeFile,unsigned char** s, int *dim){ //s= stringa da cod/decod
  2.         FILE *f; unsigned char* aus;
  3.         f=fopen(nomeFile,"r");
  4.         if(f==NULL)
  5.                 printf("\nErrore nell'apertura del file.");
  6.         if(*s!=NULL)
  7.                 free(*s);
  8.         *s=(unsigned char*)calloc(1,sizeof(unsigned char*));
  9.         if(*s==NULL){
  10.                 printf("ERRORE!");
  11.                 return;
  12.         }
  13.         fseek(f, 0, SEEK_END);
  14.         *dim=ftell(f);
  15.         rewind(f);
  16.         aus=(unsigned char*)realloc(*s,sizeof(unsigned char*)*(*dim));
  17.         if(aus==NULL){
  18.            printf("ERRORE!");
  19.            return;
  20.         }
  21.         else{
  22.             *s=aus;
  23.             fread(*s,sizeof(unsigned char),*dim,f);
  24.        }
  25.        fclose(f);


Grazie a tutti dei consigli :)

Ultima modifica effettuata da mark22 il 30/10/2017 alle 14:54
PM Quote
Avatar
Mikelius (Member)
Expert


Messaggi: 525
Iscritto: 14/04/2017

Segnala al moderatore
Postato alle 15:30
Lunedì, 30/10/2017
hai cambiato tutto il codice...
Se non usi più i blocchhi di 255 byte, perchè usi la realloc su aus?
Ti consiglio di elaborare il file con aus (anche fread), poi se tutto è ok, associare aus ad *s.
Non ti scordare il free(aus), aus dopo che non serve va deallocata.
Attento ad
Codice sorgente - presumibilmente C/C++

  1. if(f==NULL)
  2.                 printf("\nErrore nell'apertura del file.");



Non sarebbe meglio un
Codice sorgente - presumibilmente C/C++

  1. if(f==NULL){
  2.                 printf("\nErrore nell'apertura del file.");
  3.                 return;
  4.         }



una curiosità, che compilatore usi?
potresti usare la funzione stat() che, dato il nome di un file, restituisce una struttura che tra gli elementi ha pure la dimensione del file, invece che fseek e ftell, se lo scopo è solo determinare la dimensione in byte (su questo punto però aspetta conferma da altri)

PM Quote
Avatar
mark22 (Normal User)
Newbie


Messaggi: 11
Iscritto: 29/10/2017

Segnala al moderatore
Postato alle 17:22
Lunedì, 30/10/2017
Perfetto grazie mille, uso TDM-GCC.

PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 18:35
Lunedì, 30/10/2017
Così è di sicuro sbagliata, perché se il file contiene 10 caratteri, tu allocherai una stringa di 10 char, ma te ne servono 11 per avere anche il terminatore finale.
Usare realloc in questo caso non ha senso, fa direttamente una singola allocazione con malloc o calloc una volta che hai ottenuto la dimensione del file (vantaggio scontato: un punto solo in cui malloc può fallire invece di due, uno sul primo calloc e l'altro su realloc).

PM Quote
Avatar
Mikelius (Member)
Expert


Messaggi: 525
Iscritto: 14/04/2017

Segnala al moderatore
Postato alle 18:51
Lunedì, 30/10/2017
Testo quotato

Postato originariamente da lumo:

Così è di sicuro sbagliata, perché se il file contiene 10 caratteri, tu allocherai una stringa di 10 char, ma te ne servono 11 per avere anche il terminatore finale.
Usare realloc in questo caso non ha senso, fa direttamente una singola allocazione con malloc o calloc una volta che hai ottenuto la dimensione del file (vantaggio scontato: un punto solo in cui malloc può fallire invece di due, uno sul primo calloc e l'altro su realloc).



non solo, ma eseguendo la realloc/calloc/malloc con :

Codice sorgente - presumibilmente Plain Text

  1. sizeof(unsigned char*)



non si sta allocando uno spazio 4 volte maggiore rispetto al necessario?
quindi non "si nota" il +1 a dim mancante, perche in realta la dimensione allocata è 4x(*dim) e non (*dim)
o sbaglio? i puntatori sono gestiti da 4 byte per indirizzo a prenscindere dal tipo, giusto?

PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo