2009-03-09 8 views
2

AmisQuestion sur l'utilisation de l'implémentation de realloc dans le code C++

Dans notre C++, Iam utilise la méthode realloc pour redimensionner la mémoire allouée par malloc. utilisation realloc() se fait comme suit

my_Struct *strPtr =(my_struct*)malloc(sizeof(my_Struct)); 

/* an later */ 

strPtr = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR); 

maintenant wikipeadia (_http: //en.wikipedia.org/wiki/Malloc) dit que

Si la place on a fait

void *p = malloc(orig_size); 

/* and later... */ 

p = realloc(p, big_size); 

alors dans le cas où il n'est pas possible d'obtenir big_size octets de mémoire, p aura la valeur NULL et nous n'aurons plus de pointeur sur la mémoire précédemment allouée pour p, créant une fuite mémoire

Et il dit aussi que la bonne façon de corriger l'erreur ci-dessus est

void *p = malloc(orig_size); 

/* and later... */ 

void *tmp = realloc(p, big_size); 

if (tmp != NULL) 
{ 

p = tmp; /* OK, assign new, larger storage to p */ 

} 

else 

{ 

/* handle the problem somehow */ 

} 

Pouvez-vous me dire quelle est la meilleure façon d'utiliser realloc()

aussi une fois que j'ai pointeur sur un structure et puis en utilisant Realloc plus tard, puis-je utiliser un pointeur vers un vide ??

Merci beaucoup

+0

En C++, le meilleur moyen est généralement de ne pas utiliser realloc. – jalf

Répondre

7

Bien sûr, vous devez protéger contre le cas que realloc() retours NULL. C'est une allocation de mémoire, et en C (où realloc()) est principalement utilisé, je pense que les programmeurs C++ pensent qu'il est un peu bas niveau/qaint d'utiliser des appels realloc() bruts, les allocations de mémoire peuvent toujours échouer.

L'écrasement direct du pointeur avec la valeur de retour est une erreur, car cela fait tomber le pointeur d'origine et fait fuir la mémoire en cas d'échec de la réaffectation.

+0

Les programmeurs C++ ont tendance à penser que malloc/realloc ne connaissent pas vraiment les classes et les constructeurs, donc ils ne sont pas beaucoup utilisés en C++ :). –

1

Utilisez l'approche suggérée - maintenez le pointeur sur le tampon précédent jusqu'à ce que realloc soit retourné avec succès. Une fois que realloc() a réussi à retourner le bloc précédent a été libéré et tous les pointeurs à lui ont été suspendus - les ajuster. Realloc ainsi que malloc ne se soucient pas de savoir quel est le type de pointeur - vous pouvez utiliser void * ainsi que tout *. Malloc() et realloc() sont des fonctions C.

+0

si j'utilise void * pour malloc alors je vais devoir utiliser free() 2 fois d'abord pour libérer la mémoire pour malloc puis pour realloc – ronan

+0

Je ne pense pas que vous ayez besoin de le faire - si l'appel realloc réussit, Je pense qu'il prendra soin de libérer la mémoire précédente pour vous si nécessaire. Mais je ne me souviens pas à coup sûr. –

+0

Si realloc réussit, le bloc précédent sera libéré (comme si vous aviez appelé malloc-memcpy-free). Donc, tout pointeur sur le bloc précédent va maintenant se balancer. – sharptooth

5

En fait, realloc() fait malloc() et free() en fonction des arguments que vous passez:

  • Si vous lui passez un pointeur nul, realloc fait ce que fait malloc.
  • Si vous lui passez une taille nulle, realloc fait ce qui est libre.

Citation de Here, où vous avez une explication plus approfondie.

La bibliothèque C rend impossible l'extension d'un bloc de mémoire, donc C++ ne le supporte pas non plus.

Si vous voulez coller aux fonctions C, alors vous devez maintenir le pointeur de votre première allocation de mémoire lors de l'appel à realloc(). Ensuite, vous vérifiez si elle est NULL, sinon vous l'affectez, comme vous l'avez fait dans votre code Latst.

Mais peut-être que pour C++, la meilleure solution est de créer votre propre mallocateur, la solution std basée sur malloc() de C. Vérifiez this ou this.

+0

Il n'y a rien dans la bibliothèque C qui empêche Realloc d'étendre un bloc de mémoire sur place.Que cela soit possible ou non sur un système donné dépend de la mise en œuvre. –

0

Comme d'autres l'ont dit, il suffit d'utiliser correctement realloc comme suggéré. Mais la "manière C++" de faire ceci est d'utiliser un std :: vector < plutôt que de maintenir les tableaux vous-même. De cette façon, la bibliothèque standard C++ s'occupera des détails de réallocation de bas niveau (vraisemblablement en utilisant realloc()).

0

Lorsque realloc() échoue et renvoie NULL, la mémoire d'origine est intacte.
Donc, vous devriez l'utiliser comme ceci:

my_Struct* strPtr =(my_struct*)malloc(sizeof(my_Struct)); 

/* an later */ 

my_Struct* tmp = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR); 
if (tmp != NULL) 
{ 
    strPtr = tmp; 
} 
else 
{ 
    /* realloc Failed. Need to do something */ 
} 
0

Pourquoi utilisez-vous malloc et realloc? Il y a presque toujours un meilleur moyen en C++.

Si vous l'utilisez pour créer des tableaux de longueur variable, vous vous en rapprocherez certainement beaucoup avec std :: vector >, ou peut-être l'un des autres modèles de conteneur. Si vous utilisez C à la place, peut-être avec un compilateur compatible C++, alors la méthode correcte est la deuxième méthode, qui ne perd pas un bloc de mémoire entier quand il ne parvient pas à l'allouer.

La réponse à votre deuxième question dépend également de si vous utilisez C ou C++. En C, void * est un type de pointeur de données générique, et est librement convertible. En C++, void * doit être explicitement converti. Si vous écrivez en réalité C, vous devez utiliser malloc() et des amis, qui fonctionnent sur void *. Si vous écrivez réellement du C++, vous devez lancer, ce qui le rend plus gênant. Dans les deux cas, realloc() ne fonctionne pas sur des pointeurs vers struct, mais plutôt sur des pointeurs vers void.