2010-07-03 7 views
1

J'ai un fichier std :: vector d'une classe appelée OGLSHAPE.Est-ce un comportement normal pour un vecteur std ::?

chaque forme a un vecteur de SHAPECONTOUR struct qui a un vecteur de flotteur et un vecteur de vecteur de double. il a aussi un vecteur d'une structure de contour qui a un vecteur de flottant dedans. Initialement, mon programme démarre en utilisant 8,7 Mo de mémoire RAM. J'ai remarqué que lorsque j'ai commencé à les remplir, en ajoutant des doubles et des flotteurs, la mémoire s'est rapidement élevée, puis s'est stabilisée. Lorsque j'efface le vecteur OGLSHAPE, environ 19 Mo sont encore utilisés. Ensuite, si je pousse environ 150 autres formes, puis les effacer, j'utilise maintenant environ 19,3 Mo de RAM. J'aurais pensé cela logiquement, si la première fois il est passé de 8,7 à 19, que la prochaine fois il irait jusqu'à environ 30. Je ne suis pas sûr de ce que c'est. Je pensais que c'était une fuite de mémoire mais maintenant je ne suis pas sûr. Tout ce que je fais, c'est pousser les nombres dans std :: vectors, rien d'autre. Donc je m'attendrais à retrouver toute ma mémoire. Qu'est-ce qui pourrait causer ça?

Merci

* modifier, d'accord la fragmentation de la mémoire d'allouer beaucoup de petites choses, comment peut-il être résolu?

+3

Quelle plate-forme êtes-vous et comment mesurez-vous l'utilisation de la mémoire? –

+0

"Qu'est-ce qui pourrait causer cela?" Une fuite de mémoire dans OGLSHAPE pourrait facilement le faire. – SigTerm

+0

Y a-t-il une chance que vous affichiez une version simplifiée de votre code? – nas

Répondre

8

Appel std :: vecteur <> :: clear() fait tout mémoire allouée pas nécessairement libre (cela dépend de la mise en œuvre du std :: vecteur <>). Ceci est souvent fait dans le but d'optimisation pour éviter les allocations de mémoire unnessecary.

Afin de libérer vraiment la mémoire détenue par une instance juste faire:

template <typename T> 
inline void really_free_all_memory(std::vector<T>& to_clear) 
{ 
    std::vector<T> v; 
    v.swap(to_clear); 
} 

// ... 
std::vector<foo> objs; 

// ... 
// really free instance 'objs' 
really_free_all_memory(objs); 

qui crée une nouvelle (vide) par exemple et swaps avec votre instance de vecteur que vous souhaitez effacer.

+0

Je fais comme vous venez de le mentionner pour le vecteur OGLSHAPE, et je suppose que tous les autres vecteurs appellent leur destructeur – jmasterx

+0

@hkaiser, bonne astuce. Je me demande pourquoi ne pas ajouter cela comme une fonctionnalité standard dans la STL (quelque chose comme: std :: vector :: free_all_memory). – Patrick

+1

@Patrick: Je pense que parce qu'il peut facilement être exprimé comme un seul ligne: 'std :: vector () .swap (v);' Pas vraiment la peine d'ajouter à la bibliothèque standard quand c'est un idiome si commun à cette point. –

0

Utilisez les outils appropriés pour observer votre utilisation de la mémoire, par ex. (sous Windows) utilisez Process Explorer et observez les octets privés. Ne regardez pas l'espace d'adressage virtuel, car il indique l'adresse mémoire la plus élevée utilisée. La fragmentation est la cause d'une grande différence entre les deux valeurs.

réalise aussi que il y a beaucoup de couches entre votre application et le système d'exploitation:

  • le std :: vecteur fait tout mémoire immédiatement (voir la pointe de hkaiser)
  • libre pas nécessairement la C Run Time ne restitue pas toujours toute la mémoire au système d'exploitation
  • Les routines Heap du système d'exploitation peuvent ne pas pouvoir libérer toute la mémoire car elles ne peuvent libérer que des pages entières (de 4 Ko). Si 1 octet d'une page de 4 Ko est utilisé, la page ne peut pas être libérée.
0

Il y a plusieurs choses possibles ici. Premièrement, le fonctionnement de la mémoire dans la plupart des bibliothèques d'exécution C et C++ est qu'une fois qu'elle est allouée à l'application à partir du système d'exploitation, elle est rarement restituée au système d'exploitation. Lorsque vous le libérez dans votre programme, le gestionnaire de mémoire new le garde au cas où vous auriez besoin de plus de mémoire. Si vous le faites, il vous le rendra pour une réutilisation.

L'autre raison est que les vecteurs eux-mêmes ne réduisent généralement pas leur taille, même si vous les désactivez().Ils gardent la "capacité" qu'ils avaient au maximum pour qu'il soit plus rapide de les remplir à nouveau. Mais si le vecteur est jamais détruit, cette mémoire retournera à la bibliothèque d'exécution pour être à nouveau allouée. Donc, si vous ne détruisez pas vos vecteurs, ils peuvent garder la mémoire en interne pour vous. Si vous utilisez quelque chose dans le système d'exploitation pour voir l'utilisation de la mémoire, il ne sait probablement pas combien de mémoire "libre" attend dans les bibliothèques d'exécution à utiliser, plutôt que d'être restituée au système d'exploitation.

La raison pour laquelle votre utilisation de la mémoire augmente légèrement (plutôt que pas du tout) est probablement due à la fragmentation. C'est une sorte de tangente compliquée, mais il suffit de dire que l'allocation de beaucoup de petits objets peut rendre plus difficile pour la bibliothèque d'exécution de trouver un gros morceau quand elle en a besoin. Dans ce cas, il ne peut pas réutiliser une partie de la mémoire qu'il a autour de laquelle vous avez déjà libéré, car il est en beaucoup de petits morceaux. Donc, il faut aller à l'OS et demander un gros morceau.

+0

Comment pourrais-je résoudre la fragmentation de la mémoire? – jmasterx

+0

Est-ce la même chose qu'une fuite de mémoire? – jmasterx

+0

Vous n'avez généralement pas à vous soucier de la fragmentation de la mémoire. C'est naturel et devient rarement un problème sérieux. Aucune des choses que j'ai décrites n'est une fuite de mémoire, juste des barrières à vous détecter si oui ou non une fuite de mémoire existe sans faire quelque chose de plus compliqué. Utilisez un débogueur qui suit la mémoire, et il vous dira si vous avez une fuite. – SoapBox

Questions connexes