内存管理/堆栈和堆
外观
< 内存管理
在大多数本地可执行程序中,有两种类型的内存可用:基于栈的内存和基于堆的内存。
对于有栈的系统,系统栈最常用于提供帧。帧是局部化子程序信息的一种方法。一般来说,子程序的帧中必须包含返回地址(子程序完成时跳回的位置)和函数的输入参数。当调用子程序时,所有这些信息都会以特定顺序被压入栈中。当函数返回时,栈上的所有这些值都会被弹出,并被回收给系统,以便在以后的函数调用中使用。此外,子程序还可以使用栈作为本地变量的存储空间。
整个过程,即在栈上创建帧和回收帧的过程,通常是透明的,由编译器处理。程序员通常不了解这个过程,也不需要专门考虑它。
需要注意的一个陷阱是在栈上分配本地数组时可能发生。如果函数写入数组末尾以外的内存位置,就会发生一个称为缓冲区溢出的问题。缓冲区溢出是一个问题,因为数据值在栈上紧密存储,在溢出时,你可以意外覆盖这些值。如前所述,函数的返回值存储在栈上。因此,如果这个值被覆盖,函数将不会返回到正确的位置。一个勤奋的黑客可以使用这个事实来填充栈,使其包含非常特定的值,例如内存中病毒代码的地址。
栈存储是固定的。也就是说,栈上分配的空间是在编译时由编译器设置的,并且在程序执行期间不会改变。
堆是一个动态分配内存的区域,由操作系统或内存管理器库自动管理。堆上的内存会在程序执行期间经常被分配、释放和调整大小,这会导致一个称为碎片的问题。碎片是指当内存对象被分配时,它们之间留下了太小而无法容纳其他内存对象的空间。最终结果是,堆空间中的一部分无法用于进一步的内存分配。
堆也容易受到溢出情况的影响,尽管结果通常没有栈溢出那么严重。黑客通过堆溢出破坏系统并非不可能,但特别困难。