微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

_chkstk函数的目的是什么?

我最近使用了/FAsu Visual C ++编译器选项来输出特别长的成员函数定义的源代码集合。 在汇编输出中,在堆栈框架设置完成后,会有一个调用神秘的_chkstk()函数

_chkstk()上的MSDN页面没有解释调用这个函数的原因。 我也看到堆栈溢出问题在堆栈上分配一个页面大小的缓冲区会损坏内存? ,但我不明白OP和接受的答案是在说什么。

_chkstk() CRT函数的目的是什么? 它有什么作用?

如何从一个batch file中的另一个batch file从不同的目录启动一个exe文件

获取调用堆栈的大小

在窗口上使用参数调用gnuplot脚本不起作用

为什么malloc / new捕获callstack?

python subprocess.call参数的问题

从程序集调用Windows API,但没有硬编码地址

在没有堆栈的情况下在Linux上进行系统调用

在Windows关机调用WCF方法有时失败

如何调用C的extern函数并得到返回结构?

为什么我的IF比较操作失败?

在使用时,为您的线程添加额外的Windows页面。 在堆栈的最后,有一个防护页映射为不可访问的内存 – 如果程序访问它(因为它试图使用比当前映射更多的堆栈),则存在访问冲突。 操作系统发现故障,将堆栈的另一个页面映射到旧守卫页面的相同地址,创建一个新的守卫页面,并从导致违规的指令中恢复。

如果一个函数有多个局部变量页面,那么它访问的第一个地址可能会超过当前堆栈的一个页面。 因此,它会错过守护页,并触发操作系统没有意识到的访问冲突,因为需要更多的堆栈。 如果所需要的堆栈总量特别巨大,甚至可能超出守卫页面,超出分配给堆栈的虚拟地址空间的末端,并进入实际用于其他事情的内存。

所以, _chkstk确保有足够的空间用于局部变量。 你可以想象它是通过以页面大小的间隔触摸局部变量的内存,按照升序来确保它不会错过保护页(所谓的“堆栈探测”)。 我不知道它是否真的这样做,但是,可能需要更直接的路线,并指示操作系统映射一定的堆栈。 无论哪种方式,如果所需的总数大于可用于堆栈的虚拟地址空间,则操作系统可以抱怨它,而不是做一些未定义的事情。

我查看了__chkstk的代码,它每隔一页做一次重复的堆栈探测。 所以这样就不需要对操作系统进行任何调用。 rax的参数是要添加的数据的大小。 它确保目标地址(当前rsp – rax )是可访问的。 如果rax > rsp ,则为地址0执行此操作。作为一个有趣的快捷方式,它首先将地址与映射的当前最低页面gs:[10h]进行比较; 如果目标地址> =这个,那么它什么都不做。

顺便说一句,对于至少64位的代码,它是拼写有两个下划线: __chkstk__ 。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐