堆栈溢出是否总是导致分段错误?
Does a stack overflow always lead to a segmentation fault error?
在 Linux 中,当 运行ning 程序尝试使用比限制更多的堆栈 space(堆栈溢出)时,通常会导致 "segmentation fault"错误并中止执行。
是否保证超过堆栈space限制一定会导致segmentation fault错误?或者程序是否会继续 运行,可能由于数据已损坏而出现一些错误行为?
换一种说法:如果一个程序产生了错误的结果但没有崩溃,原因仍然是堆栈溢出吗?
编辑:澄清一下,这个问题不是关于"stack buffer overflow",而是关于堆栈溢出,当程序使用的堆栈space超过堆栈大小限制(限制是在Linux 由 ulimit -s
) 给出。
堆栈溢出变成访问冲突需要某种内存管理硬件。如果没有硬件辅助内存保护,过度生长的堆栈将与其他一些内存分配发生冲突,导致相互损坏。
在按需分页的虚拟内存操作系统中,堆栈的上限由保护页保护:保留的虚拟内存页(不会被分配任何东西)并标记为 "not present" 以便访问它会产生违规。保护页只有那么多字节宽;堆栈指针仍然可能意外地在保护页上递增并落入一些不相关的可写内存(例如属于堆分配的映射),在那里将造成严重破坏,而不必触发任何内存访问冲突。
在 C 语言中,我们可以通过声明大型的、未初始化的非 static
块作用域数组(例如 char array[8192]; // (twice as large as a 4096 byte guard page)
)来轻松导致较大的堆栈增量。使用像 alloca
或 C99 可变长度数组这样的特性,我们可以动态地做到这一点:我们可以编写一个程序,读取一个整数值作为 运行 时间输入,并将堆栈递增那么多。
我多年前调试过一个问题,第三方代码有调试日志宏,在宏的扩展中有一个像 char print_buf[8192]
这样的临时数组,用于格式化消息。这用于具有许多线程的多线程应用程序,其堆栈大小减少到仅 64 KB。多亏了这个 print_buf
,一个线程溢出的堆栈直接越过保护页,落在另一个线程的堆栈中,破坏了它的局部变量,导致了众所周知的 "hilarity to ensue".
在 Linux 中,当 运行ning 程序尝试使用比限制更多的堆栈 space(堆栈溢出)时,通常会导致 "segmentation fault"错误并中止执行。
是否保证超过堆栈space限制一定会导致segmentation fault错误?或者程序是否会继续 运行,可能由于数据已损坏而出现一些错误行为?
换一种说法:如果一个程序产生了错误的结果但没有崩溃,原因仍然是堆栈溢出吗?
编辑:澄清一下,这个问题不是关于"stack buffer overflow",而是关于堆栈溢出,当程序使用的堆栈space超过堆栈大小限制(限制是在Linux 由 ulimit -s
) 给出。
堆栈溢出变成访问冲突需要某种内存管理硬件。如果没有硬件辅助内存保护,过度生长的堆栈将与其他一些内存分配发生冲突,导致相互损坏。
在按需分页的虚拟内存操作系统中,堆栈的上限由保护页保护:保留的虚拟内存页(不会被分配任何东西)并标记为 "not present" 以便访问它会产生违规。保护页只有那么多字节宽;堆栈指针仍然可能意外地在保护页上递增并落入一些不相关的可写内存(例如属于堆分配的映射),在那里将造成严重破坏,而不必触发任何内存访问冲突。
在 C 语言中,我们可以通过声明大型的、未初始化的非 static
块作用域数组(例如 char array[8192]; // (twice as large as a 4096 byte guard page)
)来轻松导致较大的堆栈增量。使用像 alloca
或 C99 可变长度数组这样的特性,我们可以动态地做到这一点:我们可以编写一个程序,读取一个整数值作为 运行 时间输入,并将堆栈递增那么多。
我多年前调试过一个问题,第三方代码有调试日志宏,在宏的扩展中有一个像 char print_buf[8192]
这样的临时数组,用于格式化消息。这用于具有许多线程的多线程应用程序,其堆栈大小减少到仅 64 KB。多亏了这个 print_buf
,一个线程溢出的堆栈直接越过保护页,落在另一个线程的堆栈中,破坏了它的局部变量,导致了众所周知的 "hilarity to ensue".