[c] - Problema con free() in VS2015

di il
20 risposte

[c] - Problema con free() in VS2015

Salve, ho creato questa piccola funzione che "dovrebbe" eliminare nelle stringhe i doppi (o tripli ecc.) spazi.

Esempio: CIAO---MON--DO in CIAO-MON-DO (per fare capire meglio ho messo - al posto degli spazi, ma nel programma funziona con gli spazi)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char * doppioSpazio( char *frase )/*Togli i doppi spazi da una stringa*/
{
    /* --------------------------- DICHIARAZIONI VARIABILI --------------------------- */
    char *appoggio = NULL;                                      /* Stringa di Appoggio */
    int controllo = 0;
    size_t i = 0 ;
    size_t k = 0 ;
    size_t count = 0;
    size_t dimFrase = strlen( frase );
    size_t dimAppoggio = 0;


    /* ----------------------- ALLOCAZIONE MEMORIA E CONTROLLO  ---------------------- */
    appoggio = (char*)calloc( dimFrase , sizeof( char ) );
    if( appoggio == NULL ) {
        fprintf( stderr , "%s" , "Memoria Finita\n" );
        exit( 1 ) ;
    }

    strcpy( appoggio , frase );
    /* ---------------------------------- Do {...}WHILE() ---------------------------- */
    do {

        /* ------------------------- SCORRE TUTTA LA STRINGA ------------------------- */
        for( controllo = 0 , k = 0 , i = 0; i < strlen( appoggio ) ; i++ , k++ ) {

            /* -------- CONTROLLA SE L'ELEMENTO ED IL SUCCESSIVO SONO SPAZII --------- */
            if( appoggio[i] == ' ' && appoggio[i + 1] == ' ' ) {

                /* ---- AUMENTO SOLO UN INDICE PER SLTARE DALLA COPIA UNO SPAZIO ----- */
                i++;
                controllo = 1;
                count++;
            }

            /* --------------------- FA COMBACIARE GLI ELEMENTI ---------------------- */
            appoggio[k] = appoggio[i];
        }

        /* ----------------------- CHIUDE LA STRINGA CON '\0' ------------------------ */

        appoggio[k] = '\0';
        /* --- SERVE UN CICLO ITERATIVO PER TOGLIERE EVENTUALI DOPPI SPAZI RESIDUI --- */
    } while( controllo );

    dimAppoggio = strlen( appoggio ) ;
    if( dimFrase == ( dimAppoggio + count ) ) {
        /* ---------------------------- COPIO LA STRINGA ----------------------------- */
        strcpy( frase , appoggio);

        /* ---------------- DEALLOCO LA MEMORIA E AZZERO IL PUNTATORE ---------------- */

       //free( appoggio );
        //appoggio = NULL;

        /* -------------- RESTITUISCO LA NUOVA DIMENSIONE DELLA STRINGA -------------- */
        return appoggio;
    } else {

        /* ---------------- DEALLOCO LA MEMORIA E AZZERO IL PUNTATORE ---------------- */


        /* -------------------------- FUNZIONE NON RIUSCITA -------------------------- */
        return NULL;
    }
}

int main( void )
{
    char d[] = "ciao   mondo";
    char *g ;

    printf( "%s\n" , d );

    g = doppioSpazio( d );
    printf( "\nFrase prima:      %s\nFrase Dopo:       %s\nFrase Restituita: %s\n" , "ciao   mondo" , d, g  );
    return 0;
}

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char * doppioSpazio( char *frase )/*Togli i doppi spazi da una stringa*/
{
    /* --------------------------- DICHIARAZIONI VARIABILI --------------------------- */
    char *appoggio = NULL;                                      /* Stringa di Appoggio */
    int controllo = 0;
    size_t i = 0 ;
    size_t k = 0 ;
    size_t count = 0;
    size_t dimFrase = strlen( frase );
    size_t dimAppoggio = 0;


    /* ----------------------- ALLOCAZIONE MEMORIA E CONTROLLO  ---------------------- */
    appoggio = (char*)calloc( dimFrase , sizeof( char ) );
    if( appoggio == NULL ) {
        fprintf( stderr , "%s" , "Memoria Finita\n" );
        exit( 1 ) ;
    }

    strcpy( appoggio , frase );
    /* ---------------------------------- Do {...}WHILE() ---------------------------- */
    do {

        /* ------------------------- SCORRE TUTTA LA STRINGA ------------------------- */
        for( controllo = 0 , k = 0 , i = 0; i < strlen( appoggio ) ; i++ , k++ ) {

            /* -------- CONTROLLA SE L'ELEMENTO ED IL SUCCESSIVO SONO SPAZII --------- */
            if( appoggio[i] == ' ' && appoggio[i + 1] == ' ' ) {

                /* ---- AUMENTO SOLO UN INDICE PER SLTARE DALLA COPIA UNO SPAZIO ----- */
                i++;
                controllo = 1;
                count++;
            }

            /* --------------------- FA COMBACIARE GLI ELEMENTI ---------------------- */
            appoggio[k] = appoggio[i];
        }

        /* ----------------------- CHIUDE LA STRINGA CON '\0' ------------------------ */

        appoggio[k] = '\0';
        /* --- SERVE UN CICLO ITERATIVO PER TOGLIERE EVENTUALI DOPPI SPAZI RESIDUI --- */
    } while( controllo );

    dimAppoggio = strlen( appoggio ) ;
    if( dimFrase == ( dimAppoggio + count ) ) {
        /* ---------------------------- COPIO LA STRINGA ----------------------------- */
        strcpy( frase , appoggio);

        /* ---------------- DEALLOCO LA MEMORIA E AZZERO IL PUNTATORE ---------------- */

        free( appoggio );
        appoggio = NULL;

        /* -------------- RESTITUISCO LA NUOVA DIMENSIONE DELLA STRINGA -------------- */
        return frase;
    } else {

        /* ---------------- DEALLOCO LA MEMORIA E AZZERO IL PUNTATORE ---------------- */


        /* -------------------------- FUNZIONE NON RIUSCITA -------------------------- */
        return NULL;
    }
}

int main( void )
{
    char d[] = "ciao   mondo";
    char *g ;

    printf( "%s\n" , d );

    g = doppioSpazio( d );
    printf( "\nFrase prima:      %s\nFrase Dopo:       %s\nFrase Restituita: %s\n" , "ciao   mondo" , d, g  );
    return 0;
}
Lasciando stare l'algoritmo usato, identazione e stile commenti (ma comunque consigli su di essi sono ben accetti)
Il 1° programma funziona in VS2015, Eclipse e Dev-c++ , il secondo invece solo in Eclipse e Dev-c++. Se uso VS2015 (controllandolo via Debug) mi da errore nell'istruzione free() se la ometto, tutto funziona. qualcuno ha consigli in merito?

20 Risposte

  • Re: [c] - Problema con free() in VS2015

    A me sembra perfettibile.
    Partendo dall'inizio: perchè allochi una stringa dentro la funzione?
  • Re: [c] - Problema con free() in VS2015

    VS ha ragione ... quando scrivi

    appoggio = (char*)calloc( dimFrase , sizeof( char ));

    sbagli perché non prevedi lo spazio del terminatore. Deve essere

    appoggio = (char*)calloc( dimFrase + 1, sizeof( char ) );

    altrimenti le conseguenze sono imprevedibili ma potenzialmente disastrose. VS se ne accorge e te lo manifesta ...
  • Re: [c] - Problema con free() in VS2015

    Si si, è perfezzionabile sicuramente, sotto molti apsetti .

    Più che altro certe soluzioni le adotto per far pratica e Organizzazzione.
    Questa è una funzione di un progetto più grande (il main() l'ho scritto apposta per fare prove immediate, anche le strcpy sono introdotte per evindenziare il priblema)

    La prima versione modificava direttamente *frase , poi ho voluto provare questa funzione per non modificare *frase e farmi restituire un puntatore alla nuova stringa , la memoria l'ho allocata dentro la funzione per non portarmi dietro dal main 2 variabili.

    intanto mi sono accorto che manca il +1 nell'allocazione
    
     appoggio = (char*)calloc( dimFrase+1 , sizeof( char ) );
    che però non cancella l'errore.

    scrivevo nel mentre postavate .
  • Re: [c] - Problema con free() in VS2015

    Hai letto quello che ho scritto?
  • Re: [c] - Problema con free() in VS2015

    oregon ha scritto:


    Hai letto quello che ho scritto?
    Si, e ripeto che l'errore persiste.

    Posso disinstallare e reinstallare VS per escludere problemi al software se mi dite che con la piccola aggiustatina all'allocazione il tutto dovrebbe funzionare
  • Re: [c] - Problema con free() in VS2015

    Con la correzione l'errore non c'è più. Sicuro di avere ricompilato? Sicuro di non provare un altro codice?
  • Re: [c] - Problema con free() in VS2015

    Si....

    il resto del codice potrebbe andare?
    Ripeto, se il codice è ok sarà un errore del programma o del S.O. , faccio una bella pulizia....
  • Re: [c] - Problema con free() in VS2015

    Non è che in qualche modo, per fare prove, hai modificato il codice e non lo hai mostrato?

    Con quella modifica funzione sia su VS2012 sia su VS2013 ...

    Pubblicalo nuovamente e la provo.
  • Re: [c] - Problema con free() in VS2015

    Comunque, dato che le modifiche le fai sulla stringa originale, perché allochi una stringa temporanea??
  • Re: [c] - Problema con free() in VS2015

    L'idea era di non modificare la stringa originaria e deallocare la memoria fuori la funzione. (più che altro, per fare pratica con passaggi di puntatori e allocazionememoria) nella versione filale penso che tolgo appoggio e modifico direttamente la stringa originaria..
    
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    char * doppioSpazio( char *frase )/*Togli i doppi spazi da una stringa*/
    {
        /* --------------------------- DICHIARAZIONI VARIABILI --------------------------- */
        char *appoggio = NULL;                                      /* Stringa di Appoggio */
        int controllo = 0;
        size_t i = 0 ;
        size_t k = 0 ;
        size_t count = 0;
        size_t dimFrase = strlen( frase );
        size_t dimAppoggio = 0;
    
    
        /* ----------------------- ALLOCAZIONE MEMORIA E CONTROLLO  ---------------------- */
        appoggio = (char*)calloc( dimFrase+1 , sizeof( char ) );
        if( appoggio == NULL ) {
            fprintf( stderr , "%s" , "Memoria Finita\n" );
            exit( 1 ) ;
        }
    
        strcpy( appoggio , frase );
        /* ---------------------------------- Do {...}WHILE() ---------------------------- */
        do {
    
            /* ------------------------- SCORRE TUTTA LA STRINGA ------------------------- */
            for( controllo = 0 , k = 0 , i = 0; i < strlen( appoggio )  ; i++ , k++ ) {
    
                /* -------- CONTROLLA SE L'ELEMENTO ED IL SUCCESSIVO SONO SPAZII --------- */
                if( appoggio[i] == ' ' && appoggio[i + 1] == ' ' ) {
    
                    /* ---- AUMENTO SOLO UN INDICE PER SLTARE DALLA COPIA UNO SPAZIO ----- */
                    i++;
                    controllo = 1;
                    count++;
                }
    
                /* --------------------- FA COMBACIARE GLI ELEMENTI ---------------------- */
                appoggio[k] = appoggio[i];
            }
    
            /* ----------------------- CHIUDE LA STRINGA CON '\0' ------------------------ */
    
            appoggio[k] = '\0';
            /* --- SERVE UN CICLO ITERATIVO PER TOGLIERE EVENTUALI DOPPI SPAZI RESIDUI --- */
        } while( controllo );
    
        dimAppoggio = strlen( appoggio ) ;
        if( dimFrase == ( dimAppoggio + count ) ) {
            /* ---------------------------- COPIO LA STRINGA ----------------------------- */
            strcpy( frase , appoggio);
    
            /* ---------------- DEALLOCO LA MEMORIA E AZZERO IL PUNTATORE ---------------- */
    
            free( appoggio );
            appoggio = NULL;
    
            /* -------------- RESTITUISCO LA NUOVA DIMENSIONE DELLA STRINGA -------------- */
            return frase;
        } else {
    
            /* ---------------- DEALLOCO LA MEMORIA E AZZERO IL PUNTATORE ---------------- */
    
    
            /* -------------------------- FUNZIONE NON RIUSCITA -------------------------- */
            return NULL;
        }
    }
    
    int main( void )
    {
        char d[] = "ciao   mondo";
        char *g ;
    
        printf( "%s\n" , d );
    
        g = doppioSpazio( d );
        printf( "\nFrase prima:      %s\nFrase Dopo:       %s\nFrase Restituita: %s\n" , "ciao   mondo" , d, g  );
        return 0;
    }
  • Re: [c] - Problema con free() in VS2015

    Quel codice non dà più errore ma sinceramente è contorto e in alcuni punti "pericolosamente" incontrollato.

    In ogni caso, non lo farei certamente così ...
  • Re: [c] - Problema con free() in VS2015

    Ti do ragione, il codice è contorno prima di tutto per 2 motivi.

    1° è frutto di varie modifiche di "prova" quindi ho modificato più volte l'idea originale , quindi si è uscito contorno.
    2° Sono autodidatta , non mi appoggio a prof. o persone che possano consigliarmi i metodi più efficaci, quindi è sicuro che le soluzioni che mi invento non siano il massimo della semplicità e performance.

    riguardo al pericolosamente "incontrollato", a che punto ti riferisci? sicuramente non vedo tutti i "pericoli" che si possono celare dietro il codice (tipo il +1 nella calloc o un mancato utilizzo di free() )
  • Re: [c] - Problema con free() in VS2015

    Ad esempio nella for controlli il valore massimo di i ma all"interno aumenti i senza testare piú il suo valore
  • Re: [c] - Problema con free() in VS2015

    oregon ha scritto:


    Ad esempio nella for controlli il valore massimo di i ma all"interno aumenti i senza testare piú il suo valore
    credevo che il semplice controllo nelle condizioni del for bastasse, ma se consigli un controllo anche dentro , ok.

    Cmq ho distinstallato e Reinstallato (pulito) VS. quell'errore è sparito. Possibilmente compilava ancora la versione senza +1
Devi accedere o registrarti per scrivere nel forum
20 risposte