visual studio seguimiento pila llamadas debug c++ c windows visual-c++ callstack

c++ - seguimiento - stack trace visual studio 2017



¿Cuál es el propósito de la función_chkstk()? (2)

Miré el código para __chkstk y hace las sondas de pila repetidas en intervalos de una página. De esta forma, no es necesario realizar ninguna llamada al sistema operativo. El parámetro en rax es el tamaño de los datos que desea agregar. Asegura que se rax acceder a la dirección de destino ( rax - rax actual). Si rax > rax , lo hace para la dirección 0. Como atajo interesante, primero compara la dirección con gs:[10h] , que es la página más baja actual que se mapea; si la dirección de destino> = esto, entonces no hace nada.

Por cierto, para el código de 64 bits al menos, se escribe con dos guiones bajos: __chkstk__ .

Recientemente utilicé la opción del compilador /FAsu Visual C ++ para generar el ensamblado fuente + de una definición de función de miembro particularmente larga. En la salida del conjunto, después de configurar el marco de la pila, hay una sola llamada a una misteriosa función _chkstk() .

La página de MSDN en _chkstk() no explica la razón por la cual se llama a esta función. También he visto la pregunta sobre el desbordamiento de pila. ¿ Asignar un buffer de más tamaño de página en la pila dañará la memoria? , pero no entiendo de qué están hablando el OP y la respuesta aceptada.

¿Cuál es el propósito de la función CRT _chkstk() ? ¿Qué hace?


Páginas de Windows en una pila adicional para su hilo mientras se usa. Al final de la pila, hay una página de guardia asignada como memoria inaccesible: si el programa accede a ella (porque está tratando de usar más pila de la que está mapeada actualmente), hay una infracción de acceso. El sistema operativo detecta la falla, los mapas en otra página de la pila en la misma dirección que la página de la antigua guardia, crea una nueva página de guardia más allá de la anterior y reanuda las instrucciones que causaron la infracción.

Si una función tiene más de una página de variables locales, entonces la primera dirección a la que accede podría ser más de una página más allá del final actual de la pila. Por lo tanto, pasaría por alto la página de protección y desencadenaría una violación de acceso que el sistema operativo no se da cuenta porque se necesita más pila. Si la pila total requerida es particularmente grande, quizás podría incluso ir más allá de la página de protección, más allá del final del espacio de direcciones virtuales asignado a la pila, y en la memoria que está realmente en uso para otra cosa.

Entonces, _chkstk asegura que hay suficiente espacio para las variables locales. Puede imaginar que esto se logra tocando la memoria de las variables locales en intervalos de tamaño de página, en orden creciente, para asegurarse de que no se pierda la página de protección (las llamadas "sondas de pila"). No sé si realmente hace eso, sin embargo, posiblemente tome una ruta más directa e instruya al sistema operativo a mapear en una cierta cantidad de pila. De cualquier manera, si el total requerido es mayor que el espacio de direcciones virtual disponible para la pila, entonces el sistema operativo puede quejarse de ello en lugar de hacer algo indefinido.