Dan*_*ien 29 c c++ windows callstack visual-c++
我最近使用/FAsuVisual C++编译器选项输出特别长的成员函数定义的源+汇编.在汇编输出中,在设置堆栈帧之后,只需调用一个神秘的_chkstk()函数.
MSDN页面上_chkstk()没有解释调用此函数的原因.我也看到了Stack Overflow问题在堆栈上分配更多页面大小的缓冲区会破坏内存吗?,但我不明白OP和接受的答案是在谈论什么.
_chkstk()CRT功能的目的是什么?它有什么作用?
Ste*_*sop 40
使用时线程的额外堆栈中的Windows页面.在堆栈的末尾,有一个保护页面映射为无法访问的内存 - 如果程序访问它(因为它试图使用比当前映射更多的堆栈),则存在访问冲突.操作系统捕获故障,在与旧保护页面相同的地址处的另一个堆栈页面中映射,创建一个刚刚超出旧保护页面的新保护页面,并从导致违规的指令中恢复.
如果一个函数有多个局部变量页面,那么它访问的第一个地址可能超出了当前堆栈的一个页面.因此,它将错过防护页面并触发操作系统未实现的访问冲突,因为需要更多堆栈.如果所需的总堆栈特别大,它甚至可能超出保护页面,超出分配给堆栈的虚拟地址空间的末尾,并进入实际用于其他内容的内存.
因此,_chkstk确保有足够的空间用于局部变量.您可以想象它通过以页面大小的间隔触发局部变量的内存,按升序执行此操作,以确保它不会错过保护页面(所谓的"堆栈探测").我不知道它是否真的这样做,但是,它可能需要一个更直接的路径并指示操作系统映射到一定量的堆栈.无论哪种方式,如果所需的总量大于可用于堆栈的虚拟地址空间,那么操作系统可以抱怨它而不是做一些未定义的事情.
我查看了代码__chkstk,它确实以一页的间隔执行重复的堆栈探测.所以这样,它不需要对OS进行任何调用.参数in rax是您要添加的数据的大小.它确保可以访问目标地址(当前rsp- rax).如果rax> rsp,则为地址0执行此操作.作为一个有趣的快捷方式,它首先将地址与gs:[10h]映射的当前最低页面进行比较; 如果目标地址> = this,那么它什么都不做.
顺便说一句,至少对于64位代码,拼写有两个下划线:__chkstk__.
| 归档时间: |
|
| 查看次数: |
11438 次 |
| 最近记录: |