简体   繁体   English

桌面操作系统上的C编译器使用多少个内存页来检测堆栈溢出?

[英]How many memory pages do C compilers on desktop OSes use to detect stack overflows?

This question is related to but different from this one about variable length arrays in C99. 这个问题涉及但来自不同这一个约在C99可变长度数组。

The answers point out that one danger with allocating variable length arrays (or just large arrays of a fixed size) in the stack is that the allocation may fail silently, as opposed to, say, calling malloc , which explicitly tells the caller whether allocation succeeded. 答案指出,在堆栈中分配可变长度数组(或只是固定大小的大数组)的一个危险是分配可能会无声地失败,而不是调用malloc ,后者明确告诉调用者分配是否成功。

Modern non-embedded compilation platforms use an invalid memory zone to detect some stack overflows at no additional cost (the checks are only the checks already made for free by the MMU). 现代非嵌入式编译平台使用无效的内存区域来检测一些堆栈溢出,而无需额外成本(检查只是MMU已经免费进行的检查)。 This doesn't protect at 100% from the above problem because a very large local array may cause the stack pointer to jump over the invalid area. 这不能保证100%免受上述问题的影响,因为非常大的本地数组可能导致堆栈指针跳过无效区域。

Does any one know how many pages are typically allocated for this detection? 有没有人知道通常会为此检测分配多少页? I guess it would be at least 4KiB, but it could be more. 我想这至少是4KiB,但它可能会更多。 Is that a choice made by the compiler or the OS, and in either case, is there a way to change it? 这是由编译器或操作系统做出的选择,在任何一种情况下,有没有办法改变它?

I'm pretty sure the most common practice is using just one page, usually 4k. 我很确定最常见的做法是只使用一页,通常是4k。 A good compiler, however, will sequentially attempt to access each page of a stack frame larger than the page size on function entry (or on VLA/ alloca allocation) to ensure that a guard page is hit. 但是,一个好的编译器将依次尝试访问大于函数入口(或VLA / alloca分配)上的页面大小的堆栈帧的每个页面,以确保命中一个保护页面。 GCC can optionally do this; GCC可以选择这样做; see: http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options and the -fstack-check option. 请参阅: http//gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options-fstack-check选项。

On Windows, it's one 4KB page (at least on x86): See Description of the stack checking for Windows NT-based applications . 在Windows上,它是一个4KB页面(至少在x86上):请参阅基于Windows NT的应用程序的堆栈检查说明

This automatic growth method uses a guard page, a reserved, uncommitted, memory page that is contiguous with the committed portion of memory. 这种自动增长方法使用一个保护页面,一个保留的,未提交的内存页面,它与内存的已提交部分相邻。 When the application touches the guard page, the operating system commits that page and the next uncommitted page becomes the new guard page. 当应用程序触及防护页面时,操作系统将提交该页面,下一个未提交的页面将成为新的防护页面。 Automatic stack growth works only for the guard page and stack memory must grow in 4K, or one page, increments. 自动堆栈增长仅适用于保护页面,堆栈内存必须以4K或一页增量增长。 If the application touches another reserved but uncommitted page of stack memory before it touches the guard page, a normal page fault exception occurs and unpredictable behavior can result. 如果应用程序在触及保护页面之前触及另一个保留但未提交的堆栈内存页面,则会发生正常的页面错误异常并导致不可预测的行为。

... ...

To prevent the fault, the compiler calls the __chkstk() function each time the local allocation exceeds 4K. 为防止出现此错误,每次本地分配超过4K时,编译器都会调用__chkstk()函数。 The Windows NT __chkstk() function does not explicitly check for stack overflow as the MS-DOS version does. Windows NT __chkstk()函数没有像MS-DOS版本那样显式检查堆栈溢出。 It simply touches memory addresses every 4K from the current stack pointer location to the requested allocation. 它只是触发从当前堆栈指针位置到请求分配的每4K的内存地址。 This triggers the guard pages in the proper sequence and commits additional memory to the stack as required. 这会以正确的顺序触发保护页面,并根据需要向堆栈提交额外的内存。

For GCC, GCC Stack checking 对于GCC, GCC堆栈检查

I'm not sure how/if C99's VLA's would change the WinNT behaviour. 我不确定C99的VLA是如何改变WinNT行为的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM