Quel est le but de la fonction chkstk ()?
j'ai récemment utilisé l'option /FAsu
Visual C++ compilateur pour afficher la définition source + assemblage d'une fonction membre particulièrement longue. Dans la sortie d'assemblage, après la mise en place du cadre de pile, il y a un appel unique à une mystérieuse fonction _chkstk()
.
la page MSDN sur _chkstk()
n'explique pas la raison pour laquelle cette fonction est appelée. J'ai aussi vu la question du débordement de la pile allouer un tampon de plus d'une taille de page sur la pile va corrompre la mémoire? , mais je ne comprends pas de quoi parlent L'OP et la réponse acceptée.
Quel est le but de la fonction _chkstk()
CRT? Que faut-il faire?
2 réponses
Windows pages en pile supplémentaire pour votre thread tel qu'il est utilisé. À la fin de la pile, il y a une page de garde cartographiée comme mémoire inaccessible -- si le programme y accède (parce qu'il essaie d'utiliser plus de pile que ce qui est actuellement cartographié), il y a une violation d'accès. Le système d'exploitation saisit la faille, établit une correspondance dans une autre page de pile à la même adresse que l'ancienne page de garde, crée une nouvelle page de garde juste au-delà de l'ancienne et reprend l'instruction qui a causé la violation.
si une fonction a plus d'une page de variables locales, alors la première adresse à laquelle elle accède pourrait être plus d'une page au-delà de l'extrémité courante de la pile. Par conséquent, il manquerait la page de garde et déclencherait une violation d'accès que le système D'exploitation ne réalise pas parce que plus de stack est nécessaire. Si la pile totale nécessaire est particulièrement énorme, il pourrait peut-être même atteindre au-delà de la page de garde, au-delà de l'extrémité de l'espace d'adresse virtuelle assigné à la pile, et dans la mémoire qui est en fait en servir pour autre chose.
ainsi, _chkstk
garantit qu'il y a suffisamment d'espace pour les variables locales. Vous pouvez imaginer qu'il le fait en touchant la mémoire des variables locales aux intervalles de la taille de la page, dans l'ordre croissant, pour s'assurer qu'il ne manque pas la page de garde (soi-disant "stack sondes"). Je ne sais pas si c'est le cas, mais il est possible qu'il prenne une route plus directe et demande à L'OS de cartographier une certaine quantité de stack. Soit ainsi, si le total requis est supérieur à l'espace d'adresse virtuel disponible pour la pile, alors L'OS peut s'en plaindre au lieu de faire quelque chose d'indéfini.
j'ai regardé le code pour __chkstk
et il fait les sondes de cheminée répétées à des intervalles d'une page. De cette façon, il n'a pas besoin de passer d'appel à L'OS. Le paramètre rax
est la taille des données que vous souhaitez ajouter. Il garantit que l'Adresse cible (actuelle rsp
- rax
) est accessible. Si rax
> rsp
, il le fait pour l'adresse 0. Comme un raccourci intéressant, il compare d'abord l'adresse avec gs:[10h]
, qui est le courant la page la plus basse qui est mappée; si l'Adresse cible >= ceci, alors elle ne fait rien.
soit dit en passant, pour le code 64 bits au moins, il est orthographié avec deux underscores: __chkstk__
.