2009-05-11 10 views
2

J'utilise OS X 10.5.6. J'ai une application C++ avec une interface graphique faite avec Qt. Quand je démarre mon application, il utilise 30 Mo de mémoire (rapporté par OS X Activity Monitor RSIZE).Utilisation de la mémoire de l'application C++/Qt

J'utilise cette application pour lire des fichiers texte en mémoire, analyser les données et enfin les visualiser. Si j'ouvre (lire en mémoire, analyser, visualiser) un fichier texte de 9 Mo Le moniteur d'activité signale que mon application passe des 30 Mo de mémoire initiaux utilisés à 103 Mo.

Maintenant, si le fichier est fermé et que les données analysées et visualisées sont supprimées, la taille de l'application reste à 103 Mo. Cela ressemble à une fuite de mémoire pour moi. Mais si j'ouvre à nouveau le fichier, le lisons en mémoire, l'analysant et le visualisant, l'application reste à 103 Mo. Peu importe le nombre de fois que j'ouvre le fichier (ou un autre fichier de la même taille), l'utilisation de la mémoire de mes applications reste plus ou moins inchangée. Cela signifie-t-il que ce n'est pas une fuite de mémoire? S'il s'agissait d'une fuite, l'utilisation de la mémoire devrait continuer de croître chaque fois que le fichier est ouvert, n'est-ce pas? Le seul moment où il se développe est si j'ouvre un fichier plus volumineux que le précédent.

Est-ce normal? Cette plateforme ou bibliothèque est-elle dépendante? Est-ce une sorte de mise en cache effectuée par le système d'exploitation ou les bibliothèques?

Répondre

2

Cela semble relativement normal, mais tous les systèmes d'exploitation sont légèrement différents.

Dans le cycle de vie de l'application habituelle, l'application demande de la mémoire à l'OS et reçoit de la mémoire en gros morceaux qu'elle gère (via les bibliothèques standard C/C++). Au fur et à mesure que l'application acquiert/libère de la mémoire, tout est fait en interne dans l'application sans avoir recours au système d'exploitation jusqu'à ce que l'application ne soit pas à gauche puis un appel est fait au système d'exploitation pour un autre gros morceau.

La mémoire n'est généralement pas retournée au système d'exploitation tant que l'application ne se ferme pas (même si la plupart des systèmes d'exploitation fournissent les mécanismes nécessaires et certaines bibliothèques standard C/C++ utilisent cette fonction). Au lieu de retourner la mémoire au système d'exploitation, l'application utilise tout ce qui lui a été donné et fait sa propre gestion de la mémoire. Remarque: le fait qu'une application ait de la mémoire ne signifie pas que celle-ci occupe actuellement de la RAM sur une puce. La mémoire qui est utilisée de façon sporadique ou qui n'a pas été utilisée depuis un certain temps sera temporairement sauvegardée dans le stockage secondaire/tertiaire. Moniteur d'activité: n'est pas un outil très utile pour vérifier l'utilisation de la mémoire, car vous avez découvert qu'il n'affiche que le total réellement alloué à l'application. Il n'affiche aucune information sur la façon dont l'application a alloué cette mémoire à l'interne (la plus grande partie pourrait être désallouée). Vérifiez le dossier où XCode vit, il existe un large éventail d'outils pour examiner comment fonctionne une application fournie avec l'environnement de développement. NB: J'ai évité d'utiliser des termes comme page etc, car ils n'ont rien à voir avec C/C++/Objective C et sont tous spécifiques au système d'exploitation et au matériel.

2

Cela ressemble à un problème de fragmentation de la mémoire pour moi. La mémoire est acquise à partir du système d'exploitation dans les pages. Les pages ont généralement une taille de plusieurs Ko, par ex. 4 Ko Maintenant, si vous allouez, disons, 100 Mo de RAM pour vos objets, votre allocateur de mémoire (nouveau/malloc) demande au système d'exploitation de nombreuses pages de mémoire libre et y alloue vos objets. Lorsque votre application termine les calculs et supprime certains, même la plupart des objets précédemment alloués, mais pas tous, les objets qui n'ont pas été supprimés contiennent des pages et ne permettent pas de les renvoyer au système d'exploitation. Une page peut être retournée seulement si tous sa mémoire est libérée. Ainsi, dans les cas extrêmes, un objet 8B peut empêcher le retour d'une page complète de 4 Ko.Le système d'exploitation signale la consommation de mémoire en calculant le nombre de pages validées pour votre application, et non en prenant en compte la quantité d'espace prise par vos objets sur ces pages. Ainsi, si votre mémoire est fragmentée, les pages restent validées et la consommation de mémoire signalée reste la même.

La consommation de mémoire ne croît pas lors de la deuxième exécution, car lors de la seconde exécution, l'allocateur réutilise les pages précédemment acquises, la plupart du temps libres.

La solution aux problèmes de fragmentation consiste généralement à préallouer un plus grand bloc de mémoire et à utiliser un allocateur de mémoire personnalisé pour allouer des objets ayant une durée de vie similaire à partir de ce bloc plus grand. Ensuite, lorsque vous avez terminé avec des objets, supprimez le bloc entier.

Une autre solution consiste à basculer vers un environnement totalement récupéré comme Java ou .NET - ils ont des garbage collector qui empêchent ces problèmes.

Questions connexes