2012-02-04 14 views
20

Tengo problemas para entender cómo funciona realloc. Si malloc'ed un búfer y copiado de datos a la memoria intermedia, digamos "AB":¿Perdemos datos en un búfer después de reasignarlos?

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

entonces realloc'ed la memoria intermedia, habrá alguna perdida en los datos (incluso un solo byte)? ; o simplemente expande el buffer? :

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

código:

#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); 
} 

Respuesta

39

A realloc que aumenta el tamaño del bloque retendrá el contenido del bloque de memoria original. Incluso si el bloque de memoria no se puede cambiar de tamaño en posición, los datos antiguos se copiarán en el nuevo bloque. Para un realloc que reduce el tamaño del bloque, los datos antiguos se truncarán.

Tenga en cuenta que su llamada al realloc significará que perderá sus datos si, por algún motivo, el realloc falla. Esto se debe a que realloc falla al devolver NULL, pero en ese caso el bloque de memoria original sigue siendo válido pero no puede acceder a él más ya que ha sobrescrito el puntero será el NULL.

El patrón estándar es:

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

Tenga en cuenta también que la fundición el valor de retorno de malloc es innecesario en C y que sizeof(char) es, por definición, igual a 1.

+0

Por qué ¿No puede hacer 'buffer = realloc (tampón, newSize);'? –

+1

@ylun por las razones explicadas en la respuesta –

+0

Derecha, por lo que para evitar la pérdida de datos, primero debe verificar que la asignación sea correcta y luego reasignarla, gracias. –

4

No se pierde nada. Pero realmente debería probar si el realloc() (y el malloc() antes) "funcionó".
También el lanzamiento al valor de retorno de malloc es, en el mejor de los casos, redundante, y puede ocultar un error que el compilador habría detectado en su ausencia.

basado en la suposición de que deseas cuerdas, su uso de strncpy está mal

#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); 
} 
Cuestiones relacionadas