[C] errore malloc()?

di il
23 risposte

[C] errore malloc()?

Ciao a tutti

ho fatto un programma che comprime un testo usando sostituzioni come "xke'" apposta di perche'...
sembra funzionare tutto bene apparte il seguente errore:
quando vado a compilare il programma, se uso: "non oggi" funziona bene. se uso "non oggi perche'"(ad esempio) mi compare l'errore:


*** glibc detected *** ./bubi: munmap_chunk(): invalid pointer: 0x08b64020 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0x2270d1]
/lib/tls/i686/cmov/libc.so.6[0x2282d5]
./bubi[0x8048969]
./bubi[0x8048ae9]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x1d2b56]
./bubi[0x80487a1]
======= Memory map: ========
001bc000-002fa000 r-xp 00000000 08:01 5723 /lib/tls/i686/cmov/libc-2.10.1.so
002fa000-002fb000 ---p 0013e000 08:01 5723 /lib/tls/i686/cmov/libc-2.10.1.so
002fb000-002fd000 r--p 0013e000 08:01 5723 /lib/tls/i686/cmov/libc-2.10.1.so
002fd000-002fe000 rw-p 00140000 08:01 5723 /lib/tls/i686/cmov/libc-2.10.1.so
002fe000-00301000 rw-p 00000000 00:00 0
00797000-007b2000 r-xp 00000000 08:01 154 /lib/ld-2.10.1.so
007b2000-007b3000 r--p 0001a000 08:01 154 /lib/ld-2.10.1.so
007b3000-007b4000 rw-p 0001b000 08:01 154 /lib/ld-2.10.1.so
007c9000-007ed000 r-xp 00000000 08:01 5970 /lib/tls/i686/cmov/libm-2.10.1.so
007ed000-007ee000 r--p 00023000 08:01 5970 /lib/tls/i686/cmov/libm-2.10.1.so
007ee000-007ef000 rw-p 00024000 08:01 5970 /lib/tls/i686/cmov/libm-2.10.1.so
0089c000-0089d000 r-xp 00000000 00:00 0 [vdso]
00c46000-00c62000 r-xp 00000000 08:01 6906 /lib/libgcc_s.so.1
00c62000-00c63000 r--p 0001b000 08:01 6906 /lib/libgcc_s.so.1
00c63000-00c64000 rw-p 0001c000 08:01 6906 /lib/libgcc_s.so.1
08048000-0804a000 r-xp 00000000 00:16 20021688 /home/ifartade/Documenti/bubi
0804a000-0804b000 r--p 00001000 00:16 20021688 /home/ifartade/Documenti/bubi
0804b000-0804c000 rw-p 00002000 00:16 20021688 /home/ifartade/Documenti/bubi
08b64000-08b85000 rw-p 00000000 00:00 0 [heap]
b7869000-b786b000 rw-p 00000000 00:00 0
b7883000-b7886000 rw-p 00000000 00:00 0
bf83c000-bf851000 rw-p 00000000 00:00 0 [stack]
Aborted


il codice del programma è:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1000


char * Replace(char *origin, char *old, char *new)
{
  char *ris = (char*)malloc(sizeof(char)*strlen(origin));
  char *tmp = (char*)malloc(sizeof(char)*strlen(origin));
  ris = strcpy(ris, origin);
 
  char *pos;
  while((pos = strstr(ris, old)) != NULL) {
    memset(tmp, 0, strlen(tmp));
    tmp = strncpy(tmp,ris, pos - ris);
    tmp = strcat(tmp, new);
    tmp = strcat(tmp, pos + strlen(old));
    ris = strcpy(ris, tmp);
  }

 
  ris = (char*)realloc(ris, sizeof(char)*strlen(ris));
  free(tmp);
  free(origin);
 
  return ris;
}


int main(int argc, char ** argv) {
  char sms_in[MAX], str[MAX];
  char *ris, *mystring;
  FILE *fp;
   printf("\nIl programma comincia qui. Per uscire premere ctrl + c\n \n");
   printf("Inserire il testo da convertire (massimo 510 caratteri) e premere invio:\n");

   fgets(sms_in, MAX, stdin);


     fp = fopen("comprsms.txt", "w+");
    if (fp == NULL) {
        printf("Errore nell'apertura del file.\n");
        return 1;
    }
    
       fputs(sms_in, fp);    
 
           rewind(fp);
    
    fscanf(fp, "%s", str);
    printf("\n....%s....\n", str);
    fclose(fp);


  mystring = (char*)malloc(sizeof(char)* strlen(str));
  mystring = strcpy(mystring,str);

  ris = Replace(mystring, "ch", "k");
  ris = Replace(ris, "per", "x");
  ris = Replace(ris, "come", "cm");
  ris = Replace(ris, "questo", "qst");
  ris = Replace(ris, "niente", "nnt");
  ris = Replace(ris, "non", "nn");
  ris = Replace(ris, "oggi", "gg");
  ris = Replace(ris, "uno", "1");
  ris = Replace(ris, "sono", "sn");
  ris = Replace(ris, "tutto", "tt");
  ris = Replace(ris, "tutta", "tt");
  ris = Replace(ris, "cosa", "cs");
  ris = Replace(ris, "una", "1");
  ris = Replace(ris, "comunque", "cmq");
  ris = Replace(ris, "bene", "bn");
  ris = Replace(ris, "sei", "6");
  ris = Replace(ris, "destra", "dx");
  ris = Replace(ris, "sinistra", "sx");
  ris = Replace(ris, "messaggio", "msg");
  ris = Replace(ris, "numero", "num");
  ris = Replace(ris, "dopo", "dp");
  ris = Replace(ris, "rispondi", "risp");
  ris = Replace(ris, "risponde", "risp");
  ris = Replace(ris, "più", "+");

 
  printf("%s", ris);

  return 0;
}
 
ho provato di tutto!!
dopo varie prove e ricerche sono quasi sicuro che si tratti di un errore nella malloc... ma non ci vedo nulla di sbagliato :S

23 Risposte

  • Re: [C] errore malloc()?

    
    ==14226== Invalid write of size 1
    ==14226==    at 0x4C252CF: strcpy (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==14226==    by 0x400D14: main (prova.c:57)                                                 
    ==14226==  Address 0x51842c3 is 0 bytes after a block of size 3 alloc'd                     
    ==14226==    at 0x4C241C3: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==14226==    by 0x400CFA: main (prova.c:56)                                                 
    ==14226==                                                                                   
    ==14226== Invalid read of size 1                                                            
    ==14226==    at 0x4C25254: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==14226==    by 0x400AB4: Replace (prova.c:9)                                               
    ==14226==    by 0x400D2E: main (prova.c:59)                                                 
    ==14226==  Address 0x51842c3 is 0 bytes after a block of size 3 alloc'd                                                   
    ==14226==    at 0x4C241C3: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)                              
    ==14226==    by 0x400CFA: main (prova.c:56)
    
    --- cut ---                                                                               
    
    
  • Re: [C] errore malloc()?

    Si... l'errore è nella malloc o nella realloc... ma non riesco a capire quale sia :/
  • Re: [C] errore malloc()?

    Riga 56
    
      mystring = (char*)malloc(sizeof(char)* strlen(str));
    
  • Re: [C] errore malloc()?

    Si... ma scritto così mi pare giusto .. no?
    o forse è sbagliato str, gli devo passare qualcos'altro?
  • Re: [C] errore malloc()?

    ...se uso: "non oggi" funziona bene...
    
    str[0]='n' 
    str[1]='o'
    str[2]='n'
    str[3]='\0'
    
    strlen(str)=3 ---> mystring = malloc (3) --->
    mystring[0]=undef
    mystring[1]=undef
    mystring[2]=undef
    
    strcpy (mystring,str) ---> overflows
    
    per cui?
  • Re: [C] errore malloc()?

    Quindi, se a mystring assegno la lunghezza di str.. non sono uguali perche' in str c'è in piu il carattere di fine stringa... se ho capito bene (se no, scusate l'ignoranza.. sono ancora un principiante ^_^ )
    ho provato ad aumentare la grandezza di mystring nell'allocazione ma dà comunque il solito errore
  • Re: [C] errore malloc()?

    Hai capito bene. Bisogna tener presente il char terminatore di str ed allocare + 1 byte

    Ora controlla che non ci sia qualche errore nella funzione Replace

    Max
  • Re: [C] errore malloc()?

    Dunque.. la malloc() l'ho aggiustata scrivendola come:
      mystring = (char*)malloc(strlen(str+1)); 
    e lo stesso anche le 2 allocazioni nella funzione Replace:
      char *ris = (char*)malloc(sizeof(char)*strlen(origin+1));
      char *tmp = (char*)malloc(sizeof(char)*strlen(origin+1)); 
    ma non funziona comunque, se scrivo (per esempio) "ciao perche" mi restituisce lo stesso errore.
    se però inserisco: "non oggi perche" invece mi restituisce: "nn gg xke xke" ...mi converte 2 volte il "perche" :S

    ho provato a cambiare anche la realloc():
      ris = (char*)realloc(ris, sizeof(char)*strlen(ris+1)); 
    ma non cambia nulla :/
  • Re: [C] errore malloc()?

    Nell'errore però ci sono delle modifiche, ci ho fatto caso ora:

    invece di:

    *** glibc detected *** ./bubi: munmap_chunk(): invalid pointer: 0x08b64020 ***

    compare:

    *** glibc detected *** ./bubi: realloc(): invalid next size: 0x0933c018 ***

    ma la realloc se la cambio rimane uguale... o essendo una riallocazione va contato lo \0 precedente e quello attuale? ....
  • Re: [C] errore malloc()?

    Ehm, ehm...facciamo qualche passo indietro.

    Per +1 byte si intendeva la dimensione non l'indirizzo. Se dico:
    
    char str[]="non";
    int len=strlen(str+1);
    
    NON intendo dire che la variabile len corrisponde alla lunghezza + 1, ma intendo dire che l'indirizzo di partenza della mia stringa è al byte successivo ("on") per una lunghezza di 2.
    Se invece definisco che len deve essere uguale alla lunghezza + 1 byte dovrò scrivere:
    
    int len=strlen(str)+1;
    
    Ora, l'errore di partenza è in realtà è mio, in quanto non ho inizialmente capito il tuo livello di conoscenza. Non ho guardato il sorgente e mi sono limitato ad usare uno strumento di analisi della memoria e mostrarti la situazione.
    Non è importante avere un programma che 'funzioni' quanto effettivamente capire quello che succede, interpretando alcuni errori e usando strumenti di debugging.

    Resto comunque disponibile a aiutarti a sistemare ulteriori errori del tuo programma.

    ~Max
  • Re: [C] errore malloc()?

    Grazie per la comprensione e la disponibilità!:) .. essendo passato da un "liceo" artistico all'università di ingegneria mi sono ritrovato con moltissime lacune.. è un doppio lavoro quindi.. ma posso riuscirci ..ce la stò mettendo veramente tutta!

    cmq ho provato a modificare le malloc e realloc:
      char *ris = (char*)malloc(sizeof(char)*strlen(origin)+1);
      char *tmp = (char*)malloc(sizeof(char)*strlen(origin)+1); 
      mystring = (char*)malloc(strlen(str)+1); 
      ris = (char*)realloc(ris, sizeof(char)*strlen(ris)+1); 
    ma l'errore persiste.. solitamente quando la parola da convertire è a fine stringa. ma non sempre:
    con "non oggi perche" mi converte sempre 2 volte "xke" alla fine. con "ciao perche" invece è un overflow fisso.

    in piu, spesso il testo convertito presenta dei caratteri sbagliati come:

    ?}?nn

    dovrei inserire qualche getchar() ? .. quei caratteri sbagliati sono in piu, se non li conto la conversione sarebbe giusta..
  • Re: [C] errore malloc()?

    Bene, prima di passare alla correzione del resto del programma devi farti entrare in testa che tutte le stringhe terminano con un char aggiuntivo '\0'. Questo carattere ne determina anche la lunghezza.
  • Re: [C] errore malloc()?

    Perchè tutte quelle dichiarazioni nel main? A che cosa ti serve file txt?
    Poi, vuoi allocare dinamicamente (heap) o automaticamente (stack)?

    A te serve:
    1 buffer in input
    1 buffer in output
    oppure
    stesso buffer input/output
  • Re: [C] errore malloc()?

    Questo è un programma che devo mandare entro la mezzanotte di stasera al prof per sostenere l'orale di informatica.. inizialmente il programma faceva tutto da tastiera. non c'era il problema dell'overflow perche' la conversione la vaceva usando un ciclo quindi 1 parola per volta:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char * Replace(char *origin, char *old, char *new)
    {
      char *ris = (char*)malloc(sizeof(char)*strlen(origin));
      char *tmp = (char*)malloc(sizeof(char)*strlen(origin));
      ris = strcpy(ris, origin);
     
      char *pos;
      while((pos = strstr(ris, old)) != NULL) {
        memset(tmp, 0, strlen(tmp));
        tmp = strncpy(tmp,ris, pos - ris);
        tmp = strcat(tmp, new);
        tmp = strcat(tmp, pos + strlen(old));
        ris = strcpy(ris, tmp);
      }
      ris = (char*)realloc(ris, sizeof(char)*strlen(ris));
      free(tmp);
      free(origin);
      return ris;
    }
    
    int main(int argc, char ** argv) {
      char str[1000];
      printf("\nIl programma comincia qui. Per uscire premere ctrl + c\n \n");
      printf("Inserire il testo da convertire (massimo 510 caratteri) e premere invio:\n");
    
      do{
      scanf("%s", str);
     
      char *mystring = (char*)malloc(sizeof(char) * strlen(str));
      mystring = strcpy(mystring,str);
    
      char *ris = Replace(mystring, "ch", "k");
      ris = Replace(ris, "per", "x");
      ris = Replace(ris, "come", "cm");
      ris = Replace(ris, "questo", "qst");
      ris = Replace(ris, "niente", "nnt");
      ris = Replace(ris, "non", "nn");
      ris = Replace(ris, "oggi", "gg");
      ris = Replace(ris, "uno", "1");
      ris = Replace(ris, "sono", "sn");
      ris = Replace(ris, "tutto", "tt");
      ris = Replace(ris, "tutta", "tt");
      ris = Replace(ris, "cosa", "cs");
      ris = Replace(ris, "una", "1"); 
      ris = Replace(ris, "comunque", "cmq");
      ris = Replace(ris, "bene", "bn");
      ris = Replace(ris, "sei", "6");
      ris = Replace(ris, "destra", "dx");
      ris = Replace(ris, "sinistra", "sx");
      ris = Replace(ris, "messaggio", "msg");
      ris = Replace(ris, "numero", "num");
      ris = Replace(ris, "dopo", "dp"); 
      ris = Replace(ris, "rispondi", "risp");
      ris = Replace(ris, "risponde", "risp");
      ris = Replace(ris, "più", "+");  
    
      printf("%s", ris);
      printf(" ");
      }while(str != "\n");
    
      return 0;
    }
    
    il prof però ha detto che non va bene in questo modo perche devo lavorare da file, devo prendere in imput il testo da tastiera, salvarlo nel file e poi riprenderlo in imput da file e convertirlo.. le conversioni salvate anch'esse in un file (questo l'ho fatto copiando la parte delle conversioni in un file nominato itr.h che poi ho ripreso in imput dentro il main con #include "itr.h") ....
    questo spiega le dichiarazioni nel main e il file .txt

    per il resto, noi abbiamo studiato solo lo stack (l'heap ci è solo stato accennato).. per i buffer invece, pensavo di usarne solo uno, imput e output... ma li stò ripassando un pò ora, non ho molto chiaro il modo d'uso.. la teoria la sò, non è quello... ma ho fatto poca prattica, molti comandi ci sono stati mostrati da soli quindi devo vedere un pò come si comportano nel programma nei vari casi.
Devi accedere o registrarti per scrivere nel forum
23 risposte