Gai*_*ilu 4 c c++ gcc exception
根据gcc文档
-fstack-check
Run Code Online (Sandbox Code Playgroud)
生成代码以验证您是否超出了堆栈的边界.请注意,此开关实际上不会导致检查完成; 操作系统必须这样做.该开关导致生成代码以确保操作系统看到堆栈被扩展.
我的假设是这个额外的代码会产生异常以让操作系统知道.使用C语言时,我需要知道额外代码生成了什么异常.
谷歌也没有多大帮助.关闭我知道它是在Ada语言的情况下生成Storage_Error异常(参考).
我正在开发一种小型操作系统/调度程序,我需要捕获此异常.我正在使用C/C++.
我的GCC版本3.4.4
它不会直接生成任何异常.它生成的代码当堆栈被多个页面放大时,会生成对新分配区域中每个页面的读写访问权限.这是所有它.例:
extern void bar(char *);
void foo(void)
{
char buf[4096 * 8];
bar(buf);
}
Run Code Online (Sandbox Code Playgroud)
编译(使用gcc 4.9,在x86-64上,at -O2):
foo:
pushq %rbp
movq $-32768, %r11
movq %rsp, %rbp
subq $4128, %rsp
addq %rsp, %r11
.LPSRL0:
cmpq %r11, %rsp
je .LPSRE0
subq $4096, %rsp
orq $0, (%rsp)
jmp .LPSRL0
.LPSRE0:
addq $4128, %rsp
leaq -32768(%rbp), %rdi
call bar
leave
ret
Run Code Online (Sandbox Code Playgroud)
orq $0, (%rsp)对内存的内容没有影响(%rsp),但CPU无论如何都将其视为对该地址的读写访问.(我不知道为什么GCC %rsp在循环期间偏移4128字节,或者为什么它认为帧指针是必要的.)理论上,操作系统可以注意到这些访问并在堆栈变得太大时做一些适当的事情.对于符合POSIX标准的操作系统,这将是一个SIGSEGV信号的传递.
你可能想知道如何在OS可以看到这样的事情.硬件允许操作系统将地址空间页面指定为完全不可访问; 任何在这些页面中读取或写入内存的尝试都会触发硬件故障,操作系统可以根据需要进行处理(同样,对于符合POSIX的操作系统,交付SIGSEGV).这可以用于将"保护区"立即放置在为堆栈保留的空间的末尾之外.这就是为什么每页一次访问就足够了.
什么-fstack-check是为了保护你,要明确,就是这里的"保护区"是非常小的情况-也许只是一个页面-所以在堆栈上分配一个大的缓冲区堆栈指针移动到过去该区域进入另一个区域可访问的RAM.如果程序发生时永远不会触及保护区域内的内存,则不会立即发生崩溃,但您会在其他区域上乱涂乱画,从而导致延迟动作故障.
| 归档时间: |
|
| 查看次数: |
809 次 |
| 最近记录: |