Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 内存空间中已映射区域和未映射区域的区别是什么?_C_Heap Memory - Fatal编程技术网

C 内存空间中已映射区域和未映射区域的区别是什么?

C 内存空间中已映射区域和未映射区域的区别是什么?,c,heap-memory,C,Heap Memory,我在一篇文章中偶然发现了以下段落 堆是一个连续的(就虚拟地址而言)空间 内存有三个边界:起点、最大限制(托管) 通过sys/ressource.h的函数getrlimit(2)和setrlimit(2))和 一个叫做断点的终点。打断标记映射的结束 内存空间,即虚拟地址空间中具有 将通信转换成真实的记忆 我想更好地理解映射区域和未映射区域的概念。如果内存地址是64位长的,就像在许多现代计算机中一样,您有18446744073709551616个可能的内存地址。(这取决于处理器体系结构实际可以使用

我在一篇文章中偶然发现了以下段落

堆是一个连续的(就虚拟地址而言)空间 内存有三个边界:起点、最大限制(托管) 通过sys/ressource.h的函数getrlimit(2)和setrlimit(2))和 一个叫做断点的终点。打断标记映射的结束 内存空间,即虚拟地址空间中具有 将通信转换成真实的记忆


我想更好地理解映射区域和未映射区域的概念。

如果内存地址是64位长的,就像在许多现代计算机中一样,您有18446744073709551616个可能的内存地址。(这取决于处理器体系结构实际可以使用多少位,但地址是使用64位存储的。)这超过170亿GB,可能比计算机实际拥有的内存更多。因此,这170亿GB中只有一部分对应于实际内存。对于其余地址,内存根本不存在。内存地址和内存位置之间没有对应关系。因此,这些地址未映射

这就是简单的解释。事实上,这有点复杂。程序的内存地址不是计算机中内存芯片(物理内存)的实际内存地址。相反,它是虚拟内存。每个进程都有它自己的内存空间,即它自己的18446744073709551616地址,进程使用的内存地址由计算机硬件转换为物理内存地址。因此,一个进程可能在内存地址4711处存储了一些数据,实际上存储在这里的一个实际物理内存芯片中,另一个进程也可能在内存地址4711处存储了一些数据,但这是一个完全不同的位置,存储在那里的一个实际物理内存芯片中。进程内部虚拟内存地址被转换或映射到实际物理内存,但不是全部。其余的都是未映射的

当然,这也是一个简化的解释。您可以使用比计算机中物理内存量更多的虚拟内存。这是通过分页来完成的,也就是说,获取一些当前未使用的内存块(称为页面),并将它们存储在磁盘上,直到再次需要它们为止。(这也称为“交换”,即使该术语最初的意思是将进程的所有内存写入磁盘,而不仅仅是部分内存)


更为复杂的是,一些现代操作系统,如Linux和MacOS X(但我听说不是Windows),在分配内存时会过度使用。这意味着,即使使用磁盘,它们分配的内存地址也比计算机上存储的内存地址多。例如,我的计算机有32G的物理内存,只有4G可用于将数据分页到磁盘,不可能允许超过36G的实际可用虚拟内存。但malloc很高兴地分配了超过10万GB的数据。直到我真正尝试在所有内存中存储东西,它才连接到物理内存或磁盘。但是它是我的虚拟内存空间的一部分,所以我称之为太映射内存,即使它没有映射到任何东西。

堆中的映射区域意味着可以与物理内存一起映射的虚拟内存区域。未映射区域表示未使用的虚拟内存空间,该虚拟内存空间不指向任何物理内存


堆的映射区域和未映射区域之间的边界是系统断点。由于使用
malloc()
请求一些内存,系统断点将被移动以放大映射区域。Linux系统提供了
brk()
sbrk()
方法来增加和减少系统断点的虚拟内存地址。

您能为本文附加一个链接吗?仔细阅读
Linux
的手册页后,当使用
setrlimit
更改
数据段的大小时(即堆、BSS和初始化数据段),似乎只有
软限制
——这是问题中提到的断点——有任何明确的影响——例如返回
ENOMEM
。但是我无法确定硬限制——可能是问题中提到的
rlimit
——起到了什么作用。为了澄清,万一误解,
brk()
减小堆的大小,并
sbrk()
@c0bra,谢谢你…和
sbrk()
增加了它。除了Windows不会过度分配内存。我听说它可能会对线程堆栈这样做,以允许堆栈溢出异常处理,但它与Linux和其他操作系统所做的完全不同:
malloc
不会分配比RAM大小+页面文件更多的内存。