Je suis en train de programmer en C dans Visual Studio 2005. J'ai un programme multi-threadé, mais ce n'est pas particulièrement important ici. P>
Comment puis-je déterminer (environ) combien d'espace d'empilement mes filets utilisent? P>
La technique que je prévoyais d'utiliser est de définir la mémoire de pile à une valeur prédéterminée, disons 0xDeadbeef, exécutant le programme pendant une longue période, en faisant une pause du programme et enquête sur la pile. P>
Comment puis-je lire et écrire une mémoire de pile avec Visual Studio? P>
EDIT: voir, par exemple, "Comment déterminer l'utilisation maximale de la pile." / a> Cette question parle d'un système intégré, mais ici, j'essaie de déterminer la réponse sur un PC ordinaire. P>
4 Réponses :
La pile ne fonctionne pas comme vous l'attendez aussi. La pile est une séquence linéaire de pages, le dernier (haut) dont l'un est marqué d'un bit de garde de page. Lorsque cette page est touchée, le bit de la garde est supprimé et la page peut être utilisée. Pour une croissance ultérieure, une nouvelle page de garde est allouée. p>
Par conséquent, la réponse que vous voulez est où la page Gaurd est allouée. Mais la technique que vous proposez toucherait la page en question et, par conséquent, cela invaliderait toute la chose que vous essayez de mesurer. P>
La manière non invasive de déterminer si une page (pile) a le bit de garde est via VirtualQuery () Code>
. P>
Votre commentaire n'est pas exactement vrai. Toucher la page en question est d'accord, vraiment. La technique consiste à écrire toute la mémoire pertinente avec une valeur spécifique, puis après un long moment de fonctionnement, voir la quantité de mémoire n'a plus cette valeur là-bas.
Quypting Microsoft: "Une tentative de lecture de ou d'écriture à une page de garde provoque une exception Status_Access_Violation et désactive le statut de la page de garde. Les pages de garde agissent ainsi comme une alarme d'accès à un coup.". Non, la lecture n'est pas exemptée.
Je pense que nous parlons au-delà de l'autre.
Yup, vous avez une solution fermement en tête et vous voulez savoir comment le faire. J'ai une alternative qui est (1) en ligne avec la mise en œuvre réelle du système d'exploitation de la pile et (2) où je sais comment le faire - il suffit de vérifier combien le gardien se déplace.
Mais si je vous comprends correctement, votre solution n'a que la résolution de la page. Votre réponse est utile, mais cela ne me donne pas une réponse spécifique que j'espérais.
En fait, c'est la bonne réponse, car une page allouée à une pile est exclusivement attribuée à cette pile et à cette filetage. Par conséquent, la taille de la pile est toujours comme un certain nombre de pages. Voir aussi Options de compilateur MSVC - Des options telles que "Initial Stack Space" sont spécifiées dans Multiples de la taille de la page.
Vous pouvez utiliser des informations dans le Bloc d'information de fil Win32
Quand vous voulez Dans un fil pour découvrir combien d'espace de pile qu'il utilise, vous pouvez faire quelque chose comme ceci: p>
Windows n'engage pas immédiatement la mémoire de la pile; Au lieu de cela, il se réserve l'espace d'adressage et commet la page par page lorsqu'elle est accessible. Lire Cette page Pour plus d'informations.
En conséquence, l'espace d'adressage de la pile consiste en trois régions contiguës: p>
Cela nous permet de construire une fonction qui obtient la taille de la pile (avec granularité de la taille de la page): p> une chose à considérer: créethread < / Code> permet de spécifier la taille initiale de validation de la pile (via
dwstacksize code> paramètre, lorsque
stack_size_param_is_a_resservation code> Le drapeau n'est pas défini). Si ce paramètre est non zéro, notre fonction renvoie une valeur correcte uniquement lorsque l'utilisation de la pile devient supérieure à
dwstacksize code> valeur. P> p>
La pile ne va-t-elle pas tomber? Pourquoi ajoutez-vous les régions à l'adresse de base au lieu de la soustraire?
@Philip - La pile augmente (sur x86, au moins). J'ajoute que virtualquery code> renvoie l'adresse de base de la région d'allocation de mémoire - l'adresse du dernier octet utilisable (théoriquement) d'une pile à la baisse. Sur une plate-forme avec une pile à la hausse, le premier
virtualQuery code> aurait donné le résultat nécessaire. Je suppose que je pourrais l'illustrer avec une image; Je le ferai probablement même plus tard quand j'ai plus de temps.
@atzz j'ai une légère inquiétude à propos de cette solution (qui est assez utile). Comment savons-nous que tout en exécutant cette fonction, ou l'un des appels virtualquery que cela fait, que nous ne rencontrons pas dans la page de garde et que l'état de la pile réel change sous nous? La page de garde ne pourrait-elle pas bouger?
@ACM Il ne peut pas (si vous êtes prêt à accepter des hypothèses raisonnables sur VirtualQuery Code> Internals and Compiler Generation, la croissance de la pile doit être terminée par le premier
virtualquery code> appel) . Bien que vous puissiez appeler cette twise fn (ou n i> fois) et prendre le dernier résultat pour être extrêmement sûr. (Mais ce n'est pas à 100% aussi; par exemple, un autre processus peut infliger un
écritureProcessmemory code> sur nous et nous serions vissés :)). Le concept d'utilisation de la pile n'a de sens que pour la surveillance de la santé ou le débogage de toute façon, de sorte que la FN devrait être correcte comme cela.
Vous pouvez utiliser la fonction getthreadContext () pour déterminer le pointeur de pile actuel du fil. Utilisez ensuite VirtualQuery () pour rechercher une base de pile pour ce pointeur. Suscension Ces deux pointeurs vous donneront la taille de la pile pour le fil donné. P>