Domanda

Ho una funzione che viene chiamato più volte durante l'esecuzione del programma. In tale funzione, ho un puntatore a carattere dinamico che a ridimensionare numerose volte.

La mia domanda è:? Ho bisogno di liberare questo puntatore prima della fine della funzione

void functionName()
{
 char *variable = (char *) malloc(0);
    //variable is resized with realloc x number of times

 //should free be called here?
 return;
}

Vorrei anche sottolineare che ho cercato di liberare il puntatore, tuttavia, gdb mi dà avvertimenti quando lo faccio.

È stato utile?

Soluzione

Sì, è necessario liberarlo o ti perdita della memoria. Il codice dovrebbe essere simile a questo:

void function(void) 
{
    char *variable = (char *)malloc(0);

    variable = realloc(variable, 10);
    // do something with new memory

    variable = realloc(variable, 20);
    // do something with more new memory

    free(variable);  // clean up
}

Chiamare malloc(0) è un po 'strano, penso.

Altri suggerimenti

Alcuni punti da fare:

Non riesco a capire come si usa realloc() nel codice, ma se si sta utilizzando in questo modo, è sbagliato:

variable = realloc(variable, amount);

Quando è in grado di allocare più memoria, ritorna realloc() NULL che foglie il puntatore originale inalterato. Nella riga sopra, questo significa che è variable NULL e abbiamo perso l'accesso alla memoria è puntato, ma che la memoria non è stata liberata. La correttezza idioma è questo:

void *tmp = realloc(variable, amount);
if(tmp)
  {
    // success! variable invalid, tmp has new allocated data
    variable = tmp;
  }
else
  {
    // failure! variable valid, but same size as before, handle error
  }

Il motivo si dovrebbe usare la seconda è perché, con realloc(), il fallimento è male, ma è del tutto recuperabile in molte situazioni, a differenza malloc() dove il fallimento di solito significa "fermare tutto e muoiono."

Questa è una questione più controversa, ma è lecito chiedersi se o non si dovrebbe lanciare il valore di ritorno di malloc() e realloc() come si fa. Prendere in considerazione:

// functionally identical in C
char *a = malloc(10);
char *b = (char *)malloc(10);

In C ++, il cast deve essere fatto, perché in C ++ void * non può essere implicitamente convertito ad un altro tipo di puntatore. (Credo che questo sia un errore di lingua, ma non è il mio posto di giudice.) Se il codice è C ++, si dovrebbe utilizzare new e delete comunque. Se il codice è C, ma ha bisogno di compilare con i compilatori C ++ (per qualche motivo inane), non hai scelta, ma per cast. Se non è necessario compilare il codice C con i compilatori C ++ (che è simile a dover eseguire codice Ruby in un interprete Python), continuano a punti seguenti, che sono il motivo per cui penso che non si dovrebbe lanciare.

  1. In C89, se una funzione viene utilizzato senza essere dichiarato, sarà implicitamente dichiarato come restituzione di un int. Se, per esempio, ci siamo dimenticati di #include <stdlib.h> e abbiamo chiamato malloc(), la versione senza un cast causerebbe un errore di compilazione (cast impliciti da int a char * non sono ammessi), mentre la versione con il cast sarebbe (a torto) dire al compilatore " so che sembra pazzesco, ma gettato comunque ". La maggior parte dei compilatori vi darà un avvertimento per impliciti (o incompatibili quanto) le dichiarazioni di built-in funzioni come malloc(), ma il cast non rendere più difficile da trovare.

  2. Diciamo che avete alcuni dati:

    float *array = (float *)malloc(10 * sizeof(float));
    

    In seguito, si scopre che avete bisogno di più precisione sui dati, e hanno per rendere questo un allineamento double. Nella riga sopra, è necessario cambiare non più di 3 posti diversi:

    double *array = (double *)malloc(10 * sizeof(double));
    

    Se, d'altra parte, si aveva scritto:

    float *array = malloc(10 * sizeof *array);
    

    Si avrebbe solo bisogno di cambiamento float a double in 1 posto. Inoltre, utilizzando sempre sizeof *obj invece di sizeof(type) e non utilizza mai calchi mezzi che una chiamata in seguito a realloc() può funzionare senza alcuna modifica , durante l'utilizzo di calchi e nomi di tipo esplicite richiederebbe trovare ovunque hai chiamato realloc e cambiare i calchi e sizeofs. Inoltre, se si dimentica, e fare questo:

    double *array = (float *)malloc(10 * sizeof(float));
    

    Nella maggior parte delle piattaforme, array ora sarà solo un array di 5 elementi, assumendo l'allineamento non è spento e il compilatore non si lamenta che si sta assegnando un float * ad un double *. Alcuni considerano l'avviso i problemi del compilatore per essere utile, in quanto sottolinea le linee potenzialmente errate. Tuttavia, se evitiamo sizeof(type) ed evitare la fusione, possiamo vedere che le linee di non essere non corretta, in modo da avere il compilatore attirare l'attenzione a loro è tempo potremmo usare al programma di sprecare.

Dalle pagine man:

Se la dimensione è 0, malloc () restituisce NULL o un valore puntatore unico che può poi essere superato con successo a free ().

Quindi, credo che la risposta è "sì":)

.

Sì, è necessario chiamare gratuitamente () una volta per rilasciare il blocco di memoria. Non è necessario chiamare gratuitamente per i reallocs successivi () che si sta facendo, anche se quelli di ritorno un indirizzo diverso / puntatore. Il gestore di memoria sa che il vecchio blocco non è necessario più e libererà () esso.

Si dovrebbe essere in grado di appena free(variable) chiamata al termine. Se realloc ha mai per spostare i dati al fine di ridimensionarlo, si chiama free internamente, non è necessario preoccuparsi di questo.

Inoltre, dove si inizializza variable, si può solo impostare per NULL invece di chiamare malloc; realloc funzionerà proprio come malloc la prima volta.

Date un'occhiata ad alcune delle risposte che ho dato a un paio di domande in relazione alla gestione della memoria:

Tutto il punto fuori la cosa più ovvia di cui sopra, per ogni malloc v'è un libero, se non si dispone di una perdita di memoria , quindi è imperativo che si free la memoria quando si è finito con la variabile puntatore che è mallocd.

Spero che questo aiuti, I migliori saluti, Tom.

int main(int argc, char *argv[])
{
        char *p = malloc(sizeof(argv[1]));

        p = argv[1];
        printf("%s\n", p);
        free(p);
        return 0;
}

iam ottenere l'errore glibc

hello
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff66be94c6 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f38dca1db96]
./a.out[0x4005ed]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f38dc9c076d]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top