2012-02-04 8 views
20

Ho problemi a capire come funziona realloc. Se io malloc'ed un buffer e copiato i dati a tale buffer, diciamo "AB":Perdiamo dati in un buffer dopo la riallocazione?

+------------+ 
| A | B | \0 | 
+------------+ 

poi ho realloc'ed buffer, ci sarà persa nei dati (anche un solo byte)? ; o semplicemente amplia il buffer? :

+------------------------+ 
| A | B | \0 | ? | ? | ? | 
+------------------------+ 

codice:

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

int main(void){ 

    char* buffer = (char*) malloc(sizeof(char) * 3); 
    strncpy(buffer, "AB", 2); 

    buffer   = (char*) realloc(buffer, sizeof(char) * 6); /* Will there be any lost here? */ 
    free(buffer); 
    return(0); 
} 

risposta

39

Un realloc che aumenta la dimensione del blocco manterrà il contenuto del blocco di memoria originale. Anche se il blocco di memoria non può essere ridimensionato in posizione, i vecchi dati verranno copiati nel nuovo blocco. Per un realloc che riduce la dimensione del blocco, i vecchi dati verranno troncati.

Si noti che la chiamata a realloc significa che si perdono i dati se, per qualche motivo, lo realloc non riesce. Questo perché realloc non riesce restituendo NULL, ma in tal caso il blocco di memoria originale è ancora valido ma non è più possibile accedervi poiché è stato sovrascritto il puntatore il NULL.

Il modello standard è:

newbuffer = realloc(buffer, newsize); 
if (newbuffer == NULL) 
{ 
    //handle error 
    return ... 
} 
buffer = newbuffer; 

noti inoltre che il colare il valore restituito da malloc è inutile nella C e che sizeof(char) è, per definizione, pari a 1.

+0

Perché può non vi 'tampone = realloc (tampone, newSize);'? –

+1

@ylun per i motivi spiegati nella risposta –

+0

Proprio così, al fine di prevenire la perdita di dati, si dovrebbe prima verificare che l'allocazione abbia esito positivo e quindi riassegnare, grazie. –

4

Nulla è perso. Ma dovresti davvero provare se lo realloc() (e lo malloc() prima) "funzionava".
Anche il cast del valore di ritorno di malloc è, nella migliore delle ipotesi, ridondante e potrebbe nascondere un errore che il compilatore avrebbe rilevato in sua assenza.

basata sul presupposto che si desidera stringhe, l'uso di strncpy è sbagliato

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

int main(void) { 
    char *buffer = malloc(3); 
    if (buffer == NULL) /* no memory */ exit(EXIT_FAILURE); 

    strncpy(buffer, "AB", 2); 
    /* ATTENTTION! ATTENTION: your array is not a string. 
    ** buffer[2] is not the zero string terminator */ 

    // buffer = realloc(buffer, 6); /* Will there be any lost here? */ 
    /* If realloc returns NULL, you've just lost the only pointer to 
    ** the allocalted memory, by overwriting it with NULL. 
    ** Always `realloc` to a temporary variable */ 
    char *tmp_buffer = realloc(buffer, 6); 
    if (tmp_buffer == NULL) { 
     /* realloc failed */ 
    } else { 
     /* realloc worked, no bytes lost */ 
     buffer = tmp_buffer; 
     /* ATTENTION! ATTENTION: buffer is still not a string 
     ** buffer[0] is 'A', buffer[1] is 'B', 
     ** all other elements of buffer are indeterminate */ 
    } 

    free(buffer); 
    return(0); 
}