首页 > 解决方案 > 代码段和数据段背后的基本原理

问题描述

将内存分为代码段和数据段的基本原理是什么?我在一个来源中读到,由于冯诺依曼体系结构指令和数据存储在同一个地方,因此这种分离已经完成。

但是我想知道由于指令和数据存储在同一个地方可能导致的可能问题是什么,因为有必要将代码段和数据段分开?

为什么还要进一步划分为 bss 段、堆段和堆栈段?

标签: assemblymemory

解决方案


将程序分成代码和数据部分的最大好处之一是它允许代码部分设为只读,而数据部分可以保持可写。这可以保护代码部分不被程序意外修改,并且还允许它在运行同一程序的进程之间共享。

最近,只允许在代码段中执行代码的能力变得很重要。这是因为许多漏洞利用依赖于能够在代码段之外执行代码。分离代码和数据的另一个最近的好处是,如果代码和数据混合在一起,无序的 CPU 最终可能会推测性地执行数据,从而导致性能下降。

bss 部分作为数据部分的扩展存在。它包含初始化为零的所有程序数据。通过像这样分离零初始化数据,它允许 bss 部分实际上不存储在程序的可执行文件中。两者都节省了磁盘空间并加快了加载速度。内存中的 bss 部分只是用零填充,而不是将其读入内存。

堆和栈的相似之处在于它们都用于在程序运行时动态分配对象。两者的区别在于,分配在堆上的对象可以随时释放,而放入栈中的任何东西,只有在所有放入堆栈的东西被移除后才能被移除。每次调用函数时,都会在堆栈上为函数的参数、返回地址和局部变量等内容分配空间。当函数返回时,这些东西会从堆栈中删除。几乎所有其他动态分配的东西都分配在堆上。

传统上,在 Unix 系统上,堆位于内存中 bss 部分之后,它出现在代码和数据部分之后。当东西在堆上分配时,它会向上增长,以便在必要时为它们腾出空间。堆栈被放置在内存的末尾,并向下增长。


推荐阅读