2010-04-13 6 views
6

Cela peut être une question très simple, mais s'il vous plaît aidez-moi.supprimer & nouveau en C++

je voulais savoir ce qui se passe exactement quand je l'appelle nouveau & supprimer, par exemple dans le code ci-dessous

char * ptr=new char [10]; 

delete [] ptr; 

appel à de nouvelles déclarations me adresse de mémoire. Est-ce qu'il allouer exactement 10 octets sur le tas, Où l'information sur la taille est stockée.Quand j'appelle supprimer sur le même pointeur, je vois dans le débogueur qu'il ya beaucoup d'octets sont modifiés avant et après les 10 octets.

Y at-il un en-tête pour chaque nouveau qui contient des informations sur le nombre d'octets alloués par new.

Merci beaucoup

+2

Peut être de l'aide: http://stackoverflow.com/questions/2327848/how-does-the-delete-in-c-know-how-many-memory-locations-to-delete – codaddict

Répondre

13

Faites-le allouent exact 10 octets

C'est dépendant de l'implémentation. La garantie est "au moins 10 caractères".

Où les informations sur la taille sont-elles stockées?

Cela dépend de l'implémentation.

Y at-il un en-tête pour chaque nouveau qui contient des informations sur le nombre d'octets alloués par new?

Cela dépend de l'implémentation.

Par "cela dépend de l'implémentation", je veux dire que ce n'est pas défini dans la norme.

0
char * ptr=new char [10]; 

Vous créez un tableau de 10 de caractère en tas et stocker l'adresse de l'élément 0e dans un pointer.this est semblable à faire un malloc en C

delete [] ptr; 

Vous êtes en train de supprimer (libérer la mémoire) la mémoire de tas qui a été allouée par l'instruction précédente. Cela revient à faire un free in c.

3

Il dépend complètement de l'implémentation. En général, vous devez stocker le nombre d'éléments ailleurs. L'implémentation doit allouer suffisamment d'espace pour au moins le nombre d'éléments spécifiés, mais elle peut en allouer plus.

3

Y at-il un en-tête pour chaque nouveau qui contient des informations sur le nombre d'octets alloués par new.

Cela dépend de la plate-forme, mais oui, sur de nombreuses plates-formes.

5

Tout cela dépend du compilateur et de votre bibliothèque d'exécution. Ce n'est que exactement défini quels effets new et delete ont sur votre programme, mais comment exactement ceux-ci sont acieved n'est pas spécifié.Dans votre cas, il semble qu'un peu plus de mémoire que demandé est alloué et il stockera probablement des informations de gestion comme la taille du bloc de mémoire actuel, des informations sur les zones adjacentes d'espace libre ou des informations pour aider le débogueur à essayer de détecter les dépassements de tampon et les problèmes similaires.

2

Précisément, selon la norme, new char[10] allouera au moins 10 octets dans le tas.

Les entrailles de new et delete dépendent la mise en œuvre. Cela va donc varier du compilateur au compilateur et de la plate-forme à la plate-forme. De plus, vous pouvez trouver une variété d'algorithmes allocateurs (par exemple: TCMalloc).

Je vais vous donner un aperçu de comment pourrait fonctionner en interne, mais ne le prenez pas comme une vérité absolue. C'est écrit dans le seul but de cette explication.

En bref, l'opérateur interne new invoque malloc. Le malloc utilise une très longue liste chaînée de blocs de mémoire disponibles, alias free chain. Lorsque malloc est invoqué, il recherche cette liste pour le premier bloc suffisamment grand pour contenir la taille demandée. Après cela, il divise le bloc en deux parties, l'une avec la taille que vous avez demandé, et l'autre avec le reste, qui est ensuite ajouté à la chaîne libre. Enfin, il retourne le bloc avec la taille de la requête.

L'inverse se produit dans un appel free, qui est invoquée par suppression/suppression []. En bref, il remet le bloc fourni à free chain.

Il pourrait y avoir des astuces fantaisistes pendant les processus que j'ai décrits ci-dessus, comme trier free chain, arrondir la taille demandée à la puissance suivante de deux pour réduire la fragmentation de la mémoire, et ainsi de suite.

+0

'new' doesn pas besoin de s'appuyer sur 'malloc'.Cela dépend également de l'implémentation :) –

+0

@Axel correct, si je n'ai pas fait la 2ème phrase claire, faites le moi savoir, donc je peux clarifier. Ou même ajouter un commentaire supplémentaire avant la vue d'ensemble. C'était essentiellement pour donner une idée de comment cela fonctionne. – jweyrich

0

Il dépend de l'implémentation, mais surtout les métadonnées pour un bloc de mémoire est généralement stocké dans la zone avant l'adresse de mémoire retournée. La modification que vous avez observée avant les 10 octets était probablement la mise à jour des métadonnées pour ce bloc (probablement la taille du bloc écrit dans les métadonnées), et après que les 10 octets ont été mis à jour pour le bloc suivant (non alloué, probablement le pointeur vers le morceau suivant sur la liste libre).

Il est pas une bonne idée de jouer avec le tas comme il est portable. Cependant, si vous voulez faire un tel tas de magie, je vous suggère de mettre en place vos propres pools de mémoire (il vous suffit de récupérer un gros morceau de mémoire dans le tas et de le gérer vous-même). Un point de départ possible serait de regarder libmm.

0

Bien que les détails dépendent la mise en œuvre, un élément d'information de la mise en œuvre devra stocker est le nombre d'éléments du tableau. Ou s'il ne le stocke pas directement, il devra le dériver avec précision de la taille de bloc allouée. La raison en est que si un tableau d'objets est alloué avec new [], quand ils sont supprimés avec delete [], le destructeur de chaque objet dans le tableau devra être appelé. delete [] devra connaître le nombre d'objets à détruire. C'est pourquoi il est nécessaire de faire correspondre new avec delete et new [] avec delete [].

Questions connexes