2017-09-28 3 views
2

J'essaye de réallouer de la mémoire en utilisant realloc dans le programme ci-dessous et en vérifiant après la mémoire initiale de realloc que j'ai réagi en utilisant malloc (i = (int *) malloc (5 * sizeof (int))) programme je suis capable d'accéder aux données après realoc j'ai vérifié en utilisant un autre pointeur (ie * m). est ce comportement approprié? ou la mémoire devrait être libre une fois Realloc appelé?est-ce que re-libérer la mémoire existante?

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

    int main() 
    { 
     int *i,*jn, *m; 
     i = (int*)malloc(5 * sizeof(int)); 
     int j,k=10; 

     for(j=0 ;j<5; j++) 
     { 
     i[j] = j; 
     printf("%d \n",i[j]); 
     } 

     for(j=0 ;j<5; j++) 
     { 
     printf("%p\n",i++); 
     } 

     jn = (int *)calloc(5, sizeof(*i)); 

     for(j=0 ;j<5; j++) 
     { 
     printf("%p\n",jn++); 
     } 

     i = i-5; 
     m = i; 

     printf("m = %p %d\n",(m+1), *(m+1)); 

     i =(int *)realloc(i,8*sizeof(int)); 

     for(j=0 ;j<8; j++) 
     { 

     printf("%d\n",i[j]); 
     } 

     for(j=0 ;j<8; j++) 
     { 

     printf("%p\n",i++); 
     } 
     printf("m = %p %d\n",(m+1), *(m+1)); 

     return 0; 
} 
+1

Je considérerais cela comme une question de propriété plutôt que comme une action spécifique. Si 'realloc' réussit, il prendra la propriété de la mémoire entrante (soit en la manipulant, soit en la 'libérant') et retournera un pointeur qui peut être utilisé (" possédé ") par la fonction appelante. Si 'realloc' échoue (retourne' NULL'), votre fonction conserve la propriété de la mémoire d'origine et devrait la 'libérer' quand elle est terminée. – Myst

Répondre

4

Tout d'abord, realloc pourrait décider de

  1. Allouer un nouveau bloc de mémoire, de copier les données, et libérer l'original, ou

  2. étendre simplement/contrat le bloc d'origine « dans placer "sans allouer le nouveau.

L'approche choisie dépend de l'implémentation et de divers autres facteurs externes. Cela pourrait suivre la première approche. Ou il pourrait suivre la deuxième approche. Vous pouvez facilement déterminer quelle approche il a suivie en comparant les valeurs des pointeurs i et m après realloc. En second lieu, si realloc a décidé de suivre la première approche (c'est-à-dire d'allouer un nouveau bloc de mémoire), alors l'ancien bloc est en effet libéré par realloc. Dans ce cas, essayer d'accéder à l'emplacement mémoire d'origine conduit à un comportement indéfini.

Si realloc a décidé de suivre la deuxième approche (à savoir élargir ou rétrécir le bloc de mémoire d'origine « en place »), puis m et i gardera pointant vers le même endroit. Dans ce cas, il n'est pas surprenant de voir les mêmes données par m.

P.S. Cela signifie que le comportement de votre code est soit trivial ou undefined. Il ne peut pas vraiment être utilisé pour analyser si le comportement est "correct". Qu'avez-vous prévu de faire si la mémoire était bien libérée?

+2

La norme C11 dit (§7.22.3.5): _La fonction 'realloc' libère l'ancien objet pointé par' ptr' et renvoie un pointeur vers un nouvel objet ayant la taille spécifiée par 'size'. ... Si la mémoire du nouvel objet ne peut pas être allouée, l'ancien objet n'est pas désalloué et sa valeur est inchangée. ... La fonction 'realloc' renvoie un pointeur vers le nouvel objet (qui peut avoir la même valeur qu'un pointeur vers l'ancien objet) ou un pointeur nul si le nouvel objet n'a pas été affecté. C99 dit la même chose. C90 n'était pas explicite quant à la désallocation de l'ancienne mémoire, contrairement à C99 et C11 qui le sont. –

+0

De code ci-dessus i obtenu en dessous de la sortie. (0 0x9a40008 0x9a4000c 0x9a40010 0x9a40014 0x9a40018 0x9a40020 0x9a40024 0x9a40028 0x9a4002c 0x9a40030 m = 0x9a4000c 1 0x9a40038 0x9a4003c 0x9a40040 0x9a40044 0x9a40048 0x9a4004c 0x9a40050 0x9a40054 m = 0x9a4000c 1) avec cette sortie si realloc libérer la vieille mémoire comment se fait * m pointeur en mesure d'accéder à l'ancien emplacement de la mémoire et les données qui est présent dans la vieille mémoire emplacement –

+0

@SumitNaik L'accès à la mémoire libérée entraîne un comportement * indéfini *, qui peut se manifester à l'infini de différentes manières. Il pourrait tout aussi bien sembler "voir" les anciennes valeurs. La vraie question ici est pourquoi vous vous souciez même. Même si vous êtes en mesure d'accéder en quelque sorte à la mémoire libérée, les données résiduelles "stockées" il y a des ordures. Cela ne veut rien dire. – AnT

3

realloc équivaut à:

void * 
realloc(void *old, size_t newsz) 
{ 
    size_t old_sz = internal_function_that_finds_old_size(old); 
    void *new = malloc(newsz); 
    if (new == NULL) 
     return NULL; 
    memcpy(new, old, oldsz); 
    free(old); 
    return new; 
} 

realloc peut faire quelque chose de plus efficace, y compris de ne pas changer le pointeur et juste faire la taille allouée plus, il peut utiliser les installations du noyau pour cartographier la mémoire un autre endroit pour éviter la copie Mais en général realloc devrait être traité comme faisant exactement ce que j'ai écrit ci-dessus parce que c'est le pire des cas.

Maintenant, quand il s'agit de votre programme. Vous touchez la mémoire à travers des pointeurs invalides, tout peut arriver. m cesse d'être un pointeur valide après l'appel à realloc. Cela ne veut pas dire que personne ne vous empêchera de l'utiliser, cela signifie simplement que si vous l'utilisez, votre programme n'est plus garanti pour faire quoi que ce soit de sensé.

+1

Argh le 'nouveau' surligné en bleu! –

+0

@MatteoItalia heh. Je suppose que la coloration syntaxique sur SO croit dans le mythe C/C++. – Art