[C] realloc disalloca le celle nel ritorno a funzione

di il
34 risposte

[C] realloc disalloca le celle nel ritorno a funzione

Salve, ho un problema con il seguente codice. Il pezzo crea due linguaggi (ne mostrerò una parte dato che le operazioni saranno uguali) dove l utente decide quante sequenze immettere in una matrice e dopo una serie di validazione vado a chiedere se ne vuole inserire altre. il programma funziona ma con alcuni valori la realloc va a disalloocare mostrandomi poi uno 0*0 nel chiamante nel suo ritorno dalla funzione, quindi succede solamente in alcune situazioni. come è possibile?
printf("Crea il primo linguaggio!\n");

    /* richiesta all'utente dei dati per l'allocazione del linguaggio */   

    num_sequenze_1 = richiedi_righe_linguaggio(esito_lettura);
    if (num_sequenze_1 > 0)
        lunghezza_sequenza_1 = richiedi_colonne_linguaggio(esito_lettura);
    else 
        num_sequenze_1 = lunghezza_sequenza_1 = continua = 1;


    /* allocazione dinamica delle stringhe */

    linguaggio_1 = (char **)calloc(num_sequenze_1,
                                   sizeof(char*));
    for (j = 0;
         (j < num_sequenze_1); 
         j++)
        linguaggio_1[j] = (char *)calloc(lunghezza_sequenza_1, 
                                         sizeof(char));
    sequenza = (char *)calloc(lunghezza_sequenza_1,
                              sizeof(char));

    /* chiamata a funzione per la creazione del primo linguaggio */
    
    if (continua == 1)
        **linguaggio_1 = '0';
    else
    {
        crea_linguaggio_1(i,
                          continua,
                          sequenza_trovata,
                          j,
                          esito_lettura,
                          &num_sequenze_1,
                          &lunghezza_sequenza_1,
                          alfabeto,
                          sequenza,
                          linguaggio_1);
    }
    continua = 0;
    
 
void crea_linguaggio_1(int    i,
                       int    continua,
                       int    sequenza_trovata,
                       int    j,
                       int    esito_lettura,
                       int   *num_sequenze_1,
                       int   *lunghezza_sequenza_1,
                       char  *alfabeto,
                       char  *sequenza,
                       char **linguaggio_1)
{
   /* dichiarazione delle variabili locali alla funzione */
    int cont = 1,                           /* lavoro: contatore */
        copia_i;                            /* lavoro: copia della variabile i */

    /* inserimento e validazione sull'alfabeto delle sequenze all'interno del linguaggio */
    
    
    i = 0;
    do
    {
        for (j = 0;
             (i < *num_sequenze_1);
             i++)
        {
            do
            {
                /* inserimento delle sequenze con opportune validazioni */
                
                  inserisci_sequenze(lunghezza_sequenza_1,
                                     &cont,
                                     i,
                                     copia_i,
                                     j,
                                     esito_lettura,
                                     continua,
                                     alfabeto,
                                     sequenza);

                /* validazione della sequenza di simboli all'interno dell'insieme e se valida viene memorizzata */
        
                for (j = 0, sequenza_trovata = 1;
                     (j <= i && sequenza_trovata != 0);
                     j++)
                {
                    sequenza_trovata = strcmp(sequenza, linguaggio_1[j]);
                    if (sequenza_trovata == 0)
                    {
                        printf("Sequenza di simboli gia' memorizzata all'interno del linguaggio!");
                        printf(" Un insieme non puo' contenere 2 simboli uguali.\n");
                    }
                }
            }
            while (sequenza_trovata == 0);
            if (sequenza_trovata != 0)
            {
                strcpy(linguaggio_1[i], sequenza);
                cont++;
            }
        }
        /* richiesta all'utente per una modifica dell'allocazione */

        modifica_allocazione( esito_lettura,
                             &continua);

        if (continua == 1)
        {
            /* richiesta all'utente dei dati per l'allocazione del linguaggio */
            
           *num_sequenze_1 += richiedi_righe_linguaggio(esito_lettura);
           linguaggio_1 = (char **)realloc(linguaggio_1,
                                           *num_sequenze_1 * sizeof(char *));
            for (copia_i = 0;
                 (copia_i < *num_sequenze_1); 
                 copia_i++)
                linguaggio_1[copia_i] = (char *)realloc(linguaggio_1[copia_i],
                                                        *lunghezza_sequenza_1 * sizeof(char));
        }
    }
    while (continua == 1);
quindi l'errore viene riscontrato in alcune situazioni di reallocazione.
ad esempio un linguaggio ha le righe aa, ee, ii poi vado ad aggiungere una riga con la realloc e aggiungo oo....nel main non ritorna tutto cio ma viene eliminato tutto il precedente...come ci si dovrebbe muovere>?

34 Risposte

  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Aggiornamento(non ne vengo a capo)
    es allocazione con calloc, 3 righe e 3 colonne scrivendo nelle righe aa, ee, ii
    con la realloc vado ad aggiungere una 4a riga e ci scrivo oo....nella funzione è tutto corretto, ma tornando nella main quello che rimane è 0*..,0*..,ii.0*..., quindi i 4 spazi ci sono ma realmente rimane a 3a riga ovvero l ultima allocata con la calloc mentre il precedente e il "nuovo" di realloc non possono essere utilizzati e che quindi nel programma porterà ad un errore.....
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Evidentemente sbagli qualcosa ma per capire in breve tempo devi fornire un codice completo e compilabile in cui si manifesta il problema. Il codice andrebbe solo copiato-incollato per provarlo con chiara indicazione di come ottenere il tuo stesso errore.
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    /**********************************************************************/
    /* programma che calcola unione e differenza tra due linguaggi finiti */
    /**********************************************************************/
    
    /*****************************/
    /* inclusione delle librerie */
    /*****************************/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /*****************************************/
    /* definizioni delle costanti simboliche */
    /*****************************************/
    
    #define SIMBOLI 5
    
    /********************************/
    /* dichiarazione delle funzioni */
    /********************************/
    
    void crea_linguaggio_1(int    i,
                           int    copia_i,
                           int    continua,
                           int    sequenza_trovata,
                           int    j,
                           int    esito_lettura,
                           int   *num_sequenze_1,
                           int   *lunghezza_sequenza_1,
                           char  *alfabeto,
                           char  *sequenza,
                           char **linguaggio_1);
    
    int richiedi_righe_linguaggio(int esito_lettura);
    
    int richiedi_colonne_linguaggio(int esito_lettura);
    
    void inserisci_sequenze(int  *lunghezza_sequenza_1,
                            int  *cont,
                            int   i,
                            int   copia_i,
                            int   j,
                            int   esito_lettura,
                            int   continua,
                            char *alfabeto,
                            char *sequenza);
    
    void modifica_allocazione(int  esito_lettura,
                              int *continua);
    
    void crea_linguaggio_2(int    i,
                           int    copia_i,
                           int    continua,
                           int    sequenza_trovata,
                           int    j,
                           int    esito_lettura,
                           int   *num_sequenze_2,
                           int   *lunghezza_sequenza_2,
                           char  *alfabeto,
                           char  *sequenza,
                           char **linguaggio_2);
    
    void stampa_unione(int    i,
                       int    j,
                       int    num_sequenze_1,
                       int    num_sequenze_2,
                       int    sequenza_trovata,
                       char **linguaggio_1,
                       char **linguaggio_2,
                       char **unione);
    
    
    void costruisci_ric_differenza(int    i,
                                   int    j,
                                   int    sequenza_trovata,
                                   int    num_sequenze_1,
                                   int    num_sequenze_2,
                                   int    continua, 
                                   char **linguaggio_1,
                                   char **linguaggio_2,
                                   char **differenza);
    
    
    /******************************/
    /* definizione delle funzioni */
    /******************************/
    
    /* definizione della funzione main */
    int main(void)
    {
        /* dichiarazione delle variabili locali alla funzione */
        char   alfabeto[SIMBOLI] = {"aeiou"},      /* input: alfabeto di simboli da tenere in considerazione */
              *sequenza,
             **linguaggio_1,                       /* input: primo linguaggio finito di simboli finiti */
             **linguaggio_2,                       /* input: secondo linguaggio finito di simboli finiti */
             **differenza,                         /* output: insieme differenza tra i due linguaggi */
             **unione;                             /* output: insieme unione tra i due linguaggi */
        int    i,                                  /* lavoro: indice degli array */
               copia_i = 0,                            /* lavoro: copia della variabile i */
               continua = 0,                       /* lavoro: condizione di proseguimento*/
               sequenza_trovata = 0,               /* lavoro: parametro per la validazione della sequenza */
               num_sequenze_1,                     /* lavoro: numero delle sequenze allocate primo linguaggio */
               lunghezza_sequenza_1 = 1,           /* lavoro: lunghezza della massima sequenza primo linguaggio */
               num_sequenze_2,                     /* lavoro: numero delle sequenze allocate secondo linguaggio */ 
               j,                                  /* lavoro: indice di scorrimento dell'array */
               lunghezza_sequenza_2,               /* lavoro: lunghezza della massima sequenza secondo linguaggio */
               max_seq,                            /* lavoro: lunghezza massima delle sequenze */
               esito_lettura = 0;                  /* lavoro: esito validazione variabili */
               
        
        /*stampa dell'alfabeto utilizzabile per la creazione dei linguaggi */
    
        printf("Utilizza l'alfabeto per la creazione di 2 linguaggi.\t{");
        for (i = 0;
             (i < SIMBOLI);
             i++)
        printf("%c ",
               alfabeto[i]);
        printf("}.\n");
    
        /* creazione da parte dell'utente del secondo linguaggio finito */
    
        printf("Crea il primo linguaggio!\n");
    
        /* richiesta all'utente dei dati per l'allocazione del linguaggio */   
    
        num_sequenze_1 = richiedi_righe_linguaggio(esito_lettura);
        if (num_sequenze_1 > 0)
            lunghezza_sequenza_1 = richiedi_colonne_linguaggio(esito_lettura);
        else 
            num_sequenze_1 = lunghezza_sequenza_1 = continua = 1;
    
    
        /* allocazione dinamica delle stringhe */
    
        linguaggio_1 = calloc(num_sequenze_1,
                                       sizeof(char*));
        for (j = 0;
             (j < num_sequenze_1); 
             j++)
            linguaggio_1[j] = calloc(lunghezza_sequenza_1, 
                                             sizeof(char));
        sequenza = (char *)calloc(lunghezza_sequenza_1,
                                  sizeof(char));
    
        /* chiamata a funzione per la creazione del primo linguaggio */
        
        if (continua == 1)
            **linguaggio_1 = '0';
        else
        {
            crea_linguaggio_1(i,
                              copia_i,
                              continua,
                              sequenza_trovata,
                              j,
                              esito_lettura,
                              &num_sequenze_1,
                              &lunghezza_sequenza_1,
                              alfabeto,
                              sequenza,
                              linguaggio_1);
        }
        continua = 0;
        
        /* creazione da parte dell'utente del secondo linguaggio finito */
    
        printf("\nCrea il secondo linguaggio!\n");
    
        /* richiesta allocazione per il secondo linguaggio */
    
        num_sequenze_2 = richiedi_righe_linguaggio(esito_lettura);
        if (num_sequenze_2 > 0)
            lunghezza_sequenza_2 = richiedi_colonne_linguaggio(esito_lettura);
        else 
            num_sequenze_2 = lunghezza_sequenza_2 = continua = 1;
       
        /* allocazione dinamica delle stringhe */
    
        linguaggio_2 = calloc(num_sequenze_2,
                                           sizeof(char*));
        for (i = 0;
             (i < num_sequenze_2); 
             i++)
            linguaggio_2[i] = calloc(lunghezza_sequenza_2, 
                                             sizeof(char));
        /* chiamata a funzione per la creazione del secondo linguaggio */ 
        
        if (continua == 1)
            **linguaggio_2 = '0';
        else
        {
            crea_linguaggio_2(i,
                              copia_i,
                              continua,
                              sequenza_trovata,
                              j,
                              esito_lettura,
                              &num_sequenze_2,
                              &lunghezza_sequenza_2,
                              alfabeto,
                              sequenza,
                              linguaggio_2);
        }
       
        /* disallocazione sequenza */
        free(sequenza);
        
        /* allocazione dell'insieme unione */
        
        unione = (char **)calloc(num_sequenze_1 + num_sequenze_2,
                                 sizeof(char *));
        max_seq = lunghezza_sequenza_1;
        if (lunghezza_sequenza_2 > lunghezza_sequenza_1)
            max_seq = lunghezza_sequenza_2;
        for (j = 0;
             (j < (num_sequenze_1 + num_sequenze_2));
             j++)
            unione[j] = (char *)calloc(max_seq + 1,
                                       sizeof(char));
    
        /* stampa dell'insieme unione dei due linguaggi */
    
        stampa_unione(i,
                      j,
                      num_sequenze_1,
                      num_sequenze_2,
                      sequenza_trovata,
                      linguaggio_1,
                      linguaggio_2,
                      unione);
    
        /* allocazione dell'insieme differenza */
    
        differenza = (char **)calloc(num_sequenze_1,
                                     sizeof(char*));
        for (j = 0;
             (j < num_sequenze_1);
             j++)
            differenza[j] = (char *)calloc(lunghezza_sequenza_1,
                                           sizeof(char));
        costruisci_ric_differenza(i = 0,
                                  j = 0,
                                  sequenza_trovata,
                                  num_sequenze_1,
                                  num_sequenze_2,
                                  continua,
                                  linguaggio_1,
                                  linguaggio_2,
                                  differenza);
    
        printf("\nL'insieme differenza tra il primo e il secondo linguaggio e':\n");
        if (*differenza[0] == '0')
            printf("vuoto!\n");
        else
        {
            for (i = 0;
                 (i < num_sequenze_1);
                 i++)
            {
                    printf("%s\n",
                           differenza[i]);
            }
        }
        /* disallocazione degli insiemi */
        
        free(linguaggio_1);
        free(linguaggio_2);
        free(unione);
        free(differenza);
        
        return(0);
    }
    
    
    /* definizione della funzione per la creazione del primo linguaggio */
    void crea_linguaggio_1(int    i,
                           int    copia_i,
                           int    continua,
                           int    sequenza_trovata,
                           int    j,
                           int    esito_lettura,
                           int   *num_sequenze_1,
                           int   *lunghezza_sequenza_1,
                           char  *alfabeto,
                           char  *sequenza,
                           char **linguaggio_1)
    {
       /* dichiarazione delle variabili locali alla funzione */
        int cont = 1;                           /* lavoro: contatore */
    
        /* inserimento e validazione sull'alfabeto delle sequenze all'interno del linguaggio */
        
        
        i = 0;
        do
        {
            for (j = 0;
                 (i < *num_sequenze_1);
                 i++)
            {
                do
                {
                    /* inserimento delle sequenze con opportune validazioni */
                    
                      inserisci_sequenze(lunghezza_sequenza_1,
                                         &cont,
                                         i,
                                         copia_i,
                                         j,
                                         esito_lettura,
                                         continua,
                                         alfabeto,
                                         sequenza);
    
                    /* validazione della sequenza di simboli all'interno dell'insieme e se valida viene memorizzata */
            
                    for (j = 0, sequenza_trovata = 1;
                         (j <= i && sequenza_trovata != 0);
                         j++)
                    {
                        sequenza_trovata = strcmp(sequenza, linguaggio_1[j]);
                        if (sequenza_trovata == 0)
                        {
                            printf("Sequenza di simboli gia' memorizzata all'interno del linguaggio!");
                            printf(" Un insieme non puo' contenere 2 simboli uguali.\n");
                        }
                    }
                }
                while (sequenza_trovata == 0);
                if (sequenza_trovata != 0)
                {
                    strcpy(linguaggio_1[i], sequenza);
                    cont++;
                }
            }
            /* richiesta all'utente per una modifica dell'allocazione */
    
            modifica_allocazione( esito_lettura,
                                 &continua);
    
            if (continua == 1)
            {
                /* richiesta all'utente dei dati per l'allocazione del linguaggio */
                
               *num_sequenze_1 += richiedi_righe_linguaggio(esito_lettura);
               linguaggio_1 = realloc(linguaggio_1,
                                      *num_sequenze_1 * sizeof(char **));
                for (copia_i = 0;
                     (copia_i < *num_sequenze_1); 
                     copia_i++)
                    linguaggio_1[copia_i] = realloc(linguaggio_1[copia_i],
                                                    *lunghezza_sequenza_1 * sizeof(char*));
            }
        }
        while (continua == 1);
        printf("\nstampa primo linguaggio\n");
        for (i = 0;
             (i < *num_sequenze_1);
             i++)
            printf("%s\n",
                   linguaggio_1[i]);
    }
    
    
    /* definizione della funzione per richiedere l'allocazione del linguaggio */
    int richiedi_righe_linguaggio(int esito_lettura)
    {
        int righe;        /* output: contiene le righe di un linguaggio */       
    
        /* richiesta all'utente delle dimensioni dei linguaggi */
        do
        {
            printf("Quante sequenze finite di simboli, presi dall'alfabeto, ");
            printf("vuoi aggiungere all'interno del linguaggio? (>= 0)  ");
            esito_lettura = scanf("%d",
                                  &righe);
            if (esito_lettura != 1 || righe < 0)
                printf("Valore non accettabile!\n");
            while (getchar() != '\n');
        }
        while (esito_lettura != 1 || righe < 0);
        return(righe);
    }
    
    
    int richiedi_colonne_linguaggio(int esito_lettura)
    {
        int colonne;      /* output: contiene le colonne del linguaggio */  
        do
        {
            printf("Quale sara' la lunghezza massima della sequenza (>0)  ");
            esito_lettura = scanf("%d",
                                  &colonne);
            if (esito_lettura != 1 || colonne <= 0)
                printf("Valore non accettabile!\n");
            while (getchar() != '\n');
        }
        while (esito_lettura != 1 || colonne <= 0);
        return(colonne);
    }
    /* definizione della funzione per inserire nuove sequenze con opportune validazioni */
    void inserisci_sequenze(int  *lunghezza_sequenza_1,
                            int  *cont,
                            int   i,
                            int   copia_i,
                            int   j,
                            int   esito_lettura,
                            int   continua,
                            char *alfabeto,
                            char *sequenza)
    {
        /* inserimento e validazione delle sequenze */
        do
        {
            printf("\nInserisci la sequenza %d rispettando la lunghezza scelta:   ",
                   *cont);
            scanf("%s",
                  sequenza);
            esito_lettura = strlen(sequenza);
            for (j = 0, continua = 1;
                 (continua == 1 && esito_lettura <= (int)*lunghezza_sequenza_1 && sequenza[j] != '\0');
                 j++)
            {
                for (copia_i = continua = 0; 
                        (copia_i <= SIMBOLI && continua == 0);
                     copia_i++)
                {
                    if (sequenza[j] == alfabeto[copia_i])
                        continua = 1;
                    else
                        continua = 0;
                }
            }
            if (continua == 0)
                printf("Sequenza di simboli non valida!\n");
        }
        while (continua == 0 || esito_lettura > (int)*lunghezza_sequenza_1); 
    }
               
    /* definizione della funzione per eventuale modifica dell'allocazione*/
    void modifica_allocazione(int  esito_lettura,
                              int *continua)
    {
        do
        {
            printf("Vuoi memorizzare altre sequenze di simboli all'interno del linguaggio? (1 = si, 0 = no)  ");
            esito_lettura = scanf("%d",
                                  continua);
            if (esito_lettura != 1 || *continua < 0 || *continua > 1)
                printf("Valore non accettabile!");
            while (getchar() != '\n');
        }
        while (esito_lettura != 1 || *continua < 0 || *continua > 1);
    }
    
    void crea_linguaggio_2(int    i,
                           int    copia_i,
                           int    continua,
                           int    sequenza_trovata,
                           int    j,
                           int    esito_lettura,
                           int   *num_sequenze_2,
                           int   *lunghezza_sequenza_2,
                           char  *alfabeto,
                           char  *sequenza,
                           char **linguaggio_2)
    {
        int cont = 1;                           /* lavoro: contatore */
    
         
    
        /* inserimento e validazione sull'alfabeto delle sequenze all'interno del linguaggio */
        
        if (*num_sequenze_2 > 0)
            printf("Inserisci le sequenze di simboli nel secondo linguaggio.\n");
        sequenza = (char *)calloc(*lunghezza_sequenza_2,
                                  sizeof(char));
        i = 0;
        do
        {
            for (j = 0;
                 (i < *num_sequenze_2);
                 i++)
            {
                do
                {
                    /* inserimento delle sequenze con opportune validazioni */
                    
                      inserisci_sequenze(lunghezza_sequenza_2,
                                         &cont,
                                         i,
                                         copia_i,
                                         j,
                                         esito_lettura,
                                         continua,
                                         alfabeto,
                                         sequenza); 
                
                    /* validazione della sequenza di simboli all'interno dell'insieme e se valida viene memorizzata */
            
                    for (j = 0, sequenza_trovata = 1;
                         (j <= i && sequenza_trovata != 0);
                         j++)
                    {
                        sequenza_trovata = strcmp(sequenza, linguaggio_2[j]);
                        if (sequenza_trovata == 0)
                        {
                            printf("Sequenza di simboli gia' memorizzata all'interno del linguaggio!");
                            printf(" Un insieme non puo' contenere 2 simboli uguali.\n");
                        }
                    }
                }
                while (sequenza_trovata == 0);
                if (sequenza_trovata != 0)
                {
                    strcpy(linguaggio_2[i], sequenza);
                    cont++;
                }
            }
            /* richiesta all'utente per una modifica dell'allocazione */
    
            modifica_allocazione( esito_lettura,
                                 &continua);
    
            if (continua == 1)
            {
                /* richiesta all'utente dei dati per l'allocazione del linguaggio */
                
                *num_sequenze_2 += richiedi_righe_linguaggio(esito_lettura);
                linguaggio_2 = realloc(linguaggio_2,
                                       *num_sequenze_2 * sizeof(char *));
                for (copia_i = 0;
                     (copia_i < *num_sequenze_2); 
                     copia_i++)
                    linguaggio_2[copia_i] = realloc(linguaggio_2[copia_i],
                                                    *lunghezza_sequenza_2 * sizeof(char));
            }
        }
        while (continua == 1);
        printf("\nstampa secondo linguaggio\n");
        for (i = 0;
             (i < *num_sequenze_2);
             i++)
            printf("%s\n",
                   linguaggio_2[i]);
    }
    
    /* definizione della funzione che stampa l'unione dei due linguaggi */
    void stampa_unione(int    i,
                       int    j,
                       int    num_sequenze_1,
                       int    num_sequenze_2,
                       int    sequenza_trovata,
                       char **linguaggio_1,
                       char **linguaggio_2,
                       char **unione)
    {
        /* costruzione e stampa dell'insieme unione tra i due linguaggi */
    
        int z = num_sequenze_1;       /* lavoro: indice della matrice unione */
        for (j = 0;
             (j < num_sequenze_1);
             j++)
            strcpy(unione[j], linguaggio_1[j]);
        for (i = 0;
             (i < num_sequenze_2);
             i++)
        {
            for (j = 0, sequenza_trovata = 1;
                 (j < num_sequenze_1 && sequenza_trovata != 0);
                 j++)
                sequenza_trovata = strcmp(linguaggio_2[i], linguaggio_1[j]);
            {
                while (sequenza_trovata != 0)
                {
                    strcpy(unione[z], linguaggio_2[i]);
                    sequenza_trovata = 0;
                    z++;
                }
            }
        }
        printf("\nL'insieme unione tra i due linguaggi e':\n");
        if (*unione[0] == '0')
            printf("vuoto!\n");
        else 
        {
            for (i = 0;
                 (i < (num_sequenze_1 + num_sequenze_2));
                 i++)
            {
                printf("%s\n",
                       unione[i]);
            }
        }
    }
    
    /* definizione della funzione che stampa la differenza tra il primo e secondo linguaggio */
    void costruisci_ric_differenza(int    i,
                                   int    j,
                                   int    sequenza_trovata,
                                   int    num_sequenze_1,
                                   int    num_sequenze_2,
                                   int    continua,
                                   char **linguaggio_1,
                                   char **linguaggio_2,
                                   char **differenza)
    {
        int z;                     /*lavoro: indice matrice di supporto */
    
        /* costruzione ricorsiva dell'insieme differenza tra il primo e il secondo linguaggio */
        /* caso base */
    
        if (*linguaggio_2[num_sequenze_2 - 1] == '0')
        {
            for (j = continua = 0;
                 (j < num_sequenze_1 && continua == 0);
                 j++)
            {
                if (*linguaggio_1[j] != '0')
                    continua = 1;
            }
            if (continua == 1)
            {
                for (i = j = 0;
                     (i < num_sequenze_1);
                     i++)
                    if (*linguaggio_1[i] != '0')
                    {
                        strcpy(differenza[j], linguaggio_1[i]);
                        j++;
                    }
            }
            else 
                *differenza[0] = '0';
        }
        else
        /* caso generale */
        {
                
            for (z = 0, sequenza_trovata = 1;
                 (z < num_sequenze_1 && sequenza_trovata != 0);
                 z++)
            sequenza_trovata = strcmp(linguaggio_1[i], linguaggio_2[z]);
            z = 0;
            if (sequenza_trovata == 0)
                *linguaggio_1[i] = '0';
            *linguaggio_2[j] = '0';
    
            costruisci_ric_differenza(i + 1,
                                      j + 1,
                                      sequenza_trovata,
                                      num_sequenze_1,
                                      num_sequenze_2,
                                      continua,
                                      linguaggio_1,
                                      linguaggio_2,
                                      differenza);
        } 
    }
    questo è il codice completo. se si prova una riallocazione ed il totale delle righe è pari il codice non riportail srisultato corretto nel chaiamante..se dispari il tutto funziona.
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Intanto questa

    char alfabeto[SIMBOLI] = {"aeiou"}

    dovrebbe essere

    char alfabeto[SIMBOLI+1] = {"aeiou"}

    dato che devi prevedere il terminatore per la stringa.

    Detto questo, puoi fornire un esempio completo di input che riproduce l'errore? Cosa bisogna rispondere alle varie domande per avere l'errore? Così si risparmia tempo ad esaminare il problema...
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Alla creazione del primo linguaggio si inserisca 3 come numero di sequenze e lunghezza indifferente(es.2)
    chiederà se si vogliono aggiungere altre sequenze, allora premere 1 e digitare nuovamente 1 per aggiungere una sequenza.
    ripetere per il secondo linguaggio. il programma andra in segmentation e il motivo è nel ritorno della funzione nel main dove la realloc porta valori "sballati"
    se si sono inseriti esempio aa,ee,ii,oo riporterà corretto solo ii e alla prima occasione in cui verrà utilizzato il primo valore del linguaggio il programma cade.
    ripetendo la stessa prova con input di sequenze pari a inizialmente 4 e poi aggiungendone 1 il programma funziona correttamente. sostanzialmente quando il totale di sequenze dopo la realloc è pari ho notato che il programma cade altrimenti no. Non so dove sbaglio...
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Nella funzione crea_linguaggio_2, la riassegnazione di linguaggio_2 con quanto ritornato dalla realloc crea l'effetto che vedi:
    0) in ogni caso, la riassegnazione di linguaggio_2 non impatterà il chiamante (è la solita semantica di passaggio per copia dei parametri)
    1) se la realloc riesce a ridimensionare l area di memoria puntata realloc ritorna un puntatore uguale a quello passato in ingresso. Il puntatore nello stack frame del chiamante non è modificato, punterà alla stessa area di memoria che è ora più larga
    2) altrimenti, la realloc creerà una nuova area di memoria della nuova lunghezza e ci copierà dentro i vecchi elementi, distruggendo quella vecchia, e ritornerà il suo indirizzo che assegni a linguaggio_2.Questa modifica non è visibile al chiamante perché è fatta su una copia del puntatore. Se successivamente il chiamante tentasse di accedere a linguaggio_2 avresti probabilmente un crash.

    Questo, ragionando su due piedi, potrebbee essere un problema, da verificare se sia davvero questo o trattasi di altro. Ma il fatto che si presenti solo con alcune dimensioni di riallocazione sembra dare manforte a questa interpretazione.

    Purtroppo sono su cell per cui non posso postare un esempietto semplice per mostrare il problema concettuale, spero però di essere stato sufficientemente chiaro
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Il problema è che nel ritorno a funzione la maggior parte delle volte torna modificato e quindi torna con la dimensione più grande...altre no. non riesco a capire..
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Il motivo per cui accade è spiegato sopra, è sostanzialmente l'effetto combinato della semantica di passaggio per copia dei parametri, del comportamento di realloc (come da specifiche, puoi verificare su cppreference). Il bug nel tuo codice è essenzialmente non passare by reference il char**, e il fatto che realloc alcune volte ingrandisce l'area di memoria, altre volte ne crea una nuova, lo manifesta a volte sì, altre no.

    Più chiaro?
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Quindi dovrei passare i miei linguaggi come semplice char?... scusami se cerco conferma ma è una cosa nuova che non ho trovato in nessun libro fino a questo momento.. o forse non ho ragionato
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Sto provando ma non mi trovo con nessun cambiamento di char...
    questo bug è strano perchè quache cella me la lascia corretta altre me le punta su zone protette dal sistema
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Un passo indietro ... la semantica del passaggio dei parametri a funzione ti è ben chiara nel caso più semplice?
    Perché altrimenti, non appena si tirano in ballo parametri che sono puntatori, è assicurato fare confusione.

    che in codice del genere (pseudo, sicuramente sbaglierò a scrivere qualcosa):
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void dummy(int * ptr)
    {
       ptr = (int*) malloc(sizeof(int));
       *ptr = 5;
       printf("inside dummy, ptr[0]=%i\n", ptr[0]);
       
       // lo so, c'è un mem leak, ma il mio intento è fare capire altro qui ...
    }
    
    int main()
    {
      int * ptr = (int*)malloc(2 * sizeof(int));
      ptr[0] = 2;
      ptr[1] = 4;
      dummy(ptr);
      printf("in main, ptr[0]=%i", ptr[0]);
      free(ptr);
    }
    
    il fatto che ptr[0] non cambia nel frame nel chiamante è normale ed atteso, ed è dovuto al passaggio dei parametri per copia alla funzione. Una cosa simile accade nel tuo caso, solo più complicato perché c'è di mezzo una indirezione in più.

    ps. magari mi sto concentrando sul problema più sottile mentre ci sono altri più evidenti ed importanti
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    Si ci sono su questo
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    A questo punto, tornando al problema, nella funzione dummy le prime due righe sono una valida implementazione di realloc (qui realloco con dimensione 1) che distrugge sempre la memoria puntata e alloca nuova memoria e copia gli elementi originali.
    Dopo la chiamata alla funzione dummy, il chiamante è nei guai:
    
    #include <stdlib.h>
    #include <stdio.h>
    
    void dummy(int * ptr)
    {
       // possibile codice equivalente a realloc
       int * newPtr = (int*) malloc(sizeof(int));
       newPtr[0] = ptr[0];
       free(ptr);
       // newPtr sarebbe il puntatore ritornato da realloc
    
       newPtr[0] = 5;
       printf("inside dummy, ptr[0] = %i\n", newPtr[0]);
    }
    
    int main()
    {
      int * ptr = (int*)malloc(2 * sizeof(int));
      ptr[0] = 2;
      ptr[1] = 4;
      dummy(ptr);
    
      // l'area di memoria puntata da free è stata invalidata nella funzione
      // ogni accesso alla memoria puntata da ptr dà risultati non definiti 
      printf("in main, ptr[0] = %i", ptr[0]); // undefined behaviour
      free(ptr); // undefined behaviour: double free 
    }
    
    Ora però, il dubbio che ho è il seguente: non ti è chiaro il problema che ho evidenziato o non ti è chiaro come risolverlo ?
  • Re: [C] realloc disalloca le celle nel ritorno a funzione

    No guarda sinceramente non mi è proprio chiaro come risolverlo...non mi capacito perche con reallocazioni pari, il programma non funzione..non so cosa dire..
Devi accedere o registrarti per scrivere nel forum
34 risposte