web-dev-qa-db-fra.com

Perdons-nous des données dans un tampon après realloc'ing?

J'ai des problèmes de compréhension de la façon dont Realloc fonctionne. Si je suis un tampon et copié des données sur ce tampon, disons "AB":

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

alors je realloc'ed le tampon, qu'il y en aura perdu dans les données (même un seul octet) ?; ou il élargit simplement le tampon? :

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

code:

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

A realloc qui augmente la taille du bloc conservera le contenu du bloc de mémoire d'origine. Même si le bloc de mémoire ne peut pas être redimensionné dans placé, les anciennes données seront copiées sur le nouveau bloc. Pour un realloc qui réduit la taille du bloc, les anciennes données seront tronquées.

Notez que votre appel à realloc signifie que vous perdez vos données si, pour une raison quelconque, le realloc échoue. C'est parce que realloc échoue en retournant NULL, mais dans ce cas, le bloc de mémoire d'origine est toujours valide, mais vous ne pouvez plus y accéder puis que vous avez écrasé le pointeur le NULL.

Le modèle standard est:

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

Notez également que la valeur de la valeur de retour de malloc est inutile dans C et que sizeof(char) est, par définition, égale à 1.

53
David Heffernan

Rien n'est perdu. Mais vous devez vraiment tester si la fonction realloc() (et la fonction malloc() avant) "a travaillé".
[.

Basé sur l'hypothèse que vous voulez des chaînes, votre usage de strncpy est incorrect

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