Question

J'utilise VMMap de SysInternals regarder la mémoire allouée par mon processus de Win32 C sur Windows XP, et je vois un tas d'allocations où des portions de la mémoire allouée sont réservés mais non engagés. Pour autant que je peux dire, de mes lectures et de tests, tous les allocataires de mémoire commune (par exemple, malloc, nouveau, LocalAlloc, GlobalAlloc) utilisé dans un programme C ++ toujours allouer des blocs de mémoire entièrement engagés. Des monceaux sont un exemple courant de code mémoire des réserves mais ne commettras pas jusqu'à ce que nécessaire. Je pense que certains de ces blocs sont des tas de Windows / CRT, mais il semble y avoir plus de ces types de blocs que j'attendre pour des tas. Je vois l'ordre de 30 de ces blocs dans mon processus, entre 64k et 8MB, et je sais que mon code n'appelle jamais intentionnellement VirtualAlloc à allouent réservé, la mémoire non validée.

Voici quelques exemples de VMMap: http://www.flickr. com / photos / 95123032 @ N00 / 5280550393 /

Que attribuerait ces blocs de mémoire, où une grande partie de celui-ci est réservé mais pas commis? Serait-il logique que mon processus a 30 tas? Merci.

Était-ce utile?

La solution

I figured it out - il est le tas CRT qui obtient alloué par les appels à malloc. Si vous allouez une grande partie de la mémoire (par exemple, 2 Mo) à l'aide malloc, il alloue un seul bloc engagé de mémoire. Mais si vous allouez plus petits morceaux (par exemple 177kb), il réservera un morceau de 1 Mo de mémoire, mais engager seulement à peu près ce que vous avez demandé (par exemple, 184kb pour ma demande de 177kb).

Lorsque vous libérez ce petit morceau, que de plus gros morceaux 1 Mo n'est pas retourné au système d'exploitation. Tout sauf 4k est non engagée, mais le plein 1 Mo reste réservé. Si vous appelez ensuite malloc à nouveau, il va tenter d'utiliser ce morceau 1 Mo pour satisfaire votre demande. Si elle ne peut pas répondre à votre demande avec la mémoire qu'il est déjà réservé, il attribuera une nouvelle partie de la mémoire qui est le double de la précédente allocation (dans mon cas, il est passé de 1 Mo à 2 Mo). Je ne sais pas si ce modèle de doublement continue ou non.

Pour revenir réellement votre mémoire libérée à l'OS, vous pouvez appeler _heapmin. Je pense que cela ferait un avenir grande allocation plus de chances de réussir, mais il serait tout dépendra de la fragmentation de la mémoire, et peut-être heapmin accapare déjà appelé si une allocation échoue (?), Je ne suis pas sûr. Il y aurait également un impact sur les performances depuis heapmin libérerait la mémoire (en prenant le temps) et malloc aurait alors besoin de réallouer à partir du système d'exploitation en cas de besoin à nouveau. Ces informations sont pour Windows / XP 32, votre kilométrage peut varier.

Mise à jour: Dans mes tests, heapmin n'a absolument rien fait. Et le tas malloc est utilisé uniquement pour les blocs qui sont à moins de 512 Ko. Même s'il y a d'espace libre MBs contigus dans le tas malloc, il ne sera pas l'utiliser pour les demandes plus 512kb. Dans mon cas, ce libéré, la mémoire malloc utilisé, mais réservé mâché énormes parties de mon processus de l'espace d'adressage de 2 Go, pour aboutir finalement à des échecs d'allocation de mémoire. Et puisque heapmin ne retourne pas la mémoire à l'OS, je ne l'ai pas trouvé de solution à ce problème, autre que le redémarrage de mon processus ou d'écrire mon propre gestionnaire de mémoire.

Autres conseils

Peuvent-ils être les DLL chargées dans votre processus? DLL (et l'exécutable) sont mémoire mappée dans l'espace d'adressage du processus. Je crois que cet espace de réserves initialement juste. L'espace est soutenu par les fichiers eux-mêmes (au moins au début) plutôt que le fichier d'échange.

Seul le code qui est effectivement touché se paginée. Si je comprends bien la terminologie, c'est quand il est commis.

Vous pourriez confirmer cela en exécutant votre application dans un débogueur et en regardant les modules qui sont chargés et en comparant leurs emplacements et tailles à ce que vous voyez dans VMMap.

Chaque fois qu'un thread est créé dans votre application un certain (configurable) quantité de mémoire sera réservée dans l'espace d'adressage pour la pile d'appel du fil. Il n'y a pas besoin de commettre toute la mémoire réservée à moins que votre fil va effectivement avoir besoin de toute cette mémoire. Ainsi seulement les besoins en partie à engager.

Si plus que le montant engagé de mémoire est nécessaire, il sera possible d'obtenir plus de mémoire système.

L'examen pratique est que la mémoire réservée est une limite stricte de la taille de la pile qui réduit l'espace d'adressage disponible à la demande. Cependant, en ne commettant une partie de la réserve, nous ne devons pas consommer la même quantité de mémoire du système jusqu'à ce que nécessaire.

Par conséquent, il est possible pour chaque thread d'avoir une partie de la mémoire réservée non engagée. Je ne suis pas sûr de ce type de page sera dans ces cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top