C对内存的管理 malloc最大值
问题引入:在程序中malloc最大值能是3G么,2G可以么
问题引申:静态变量(全局变量、常量)能申请的空间上限是多少
问题环境32位计算机,OS:Linux
代码段:代码的可执行文件或二进制文件
数据段:未初始化的数据存储在BSS(Block Started by Symbol)段,已经初始化的(所有全局变量,静态变量和常量)存储在data段
堆heap:进程运行时分配的地址空间(使用calloc, malloc函数申请)
栈stack:用于局部变量,传递参数,返回值等
注意:可以粗略的将heap理解为垃圾桶,里面东西很乱,找东西慢,向上增长。相比stack更有结构感,访问速度快,向下增长(向低地址增长)。对于Linux,内核按照1:3比例将地址空间分为1G高地址的内核空间以及0~3G的低地址用户进程可访问空间。stack位于3G空间处向下增长;heap位于低地址,向高地址增长,防止了申请地址时地址越界进入内核区或是进入了数据段等情况的发生。此外当进程开始时stack一般不会再增加反而会减少,而heap则可能随着进程的进行而增加;stack是系统分配给线程的,在方法执行后自动释放所占空间,而heap空间则是分配给进程的,随进程创建而申请随进程退出而释放。
Linux内存地址划分如下:(内核高端3-4G地址映射到物理地址的0-1G处在此不做展开说明)
图片来源:http://duartes.org/gustavo/blog/category/linux
通过以上介绍,对本文初提出的问题得到答案:
问题1:用户态总共可访问的空间是3G,所以申请3G空间肯定越界了。注意:Linux在申请空间时并不是一次给予要求的所有空间,在需要时通过缺页异常按页进行分配。此外malloc申请空间在heap中,具体能申请的最大值还要看stack已占据的大小,heap中已经被分配的大小等因素决定,但2G明显小于3G,在上述条件满足时可申请。
问题2:静态变量(全局变量、常量)被存放在data段或bss段,查看某进程(此处为test)开始地址使用nm指令查看文件符号例如:
s@ubuntu:/host/linux-kernel/$ nm test
0000000000600e48 d __JCR_END__
0000000000600e48 d __JCR_LIST__
0000000000601020 A __bss_start
0000000000601010 D __data_start
0000000000400660 t __do_global_ctors_aux
0000000000400460 t __do_global_dtors_aux
0000000000601018 D __dso_handle
w __gmon_start__
申请的全局变量大小要根据操作系统对数据段分配的空间大小。
参考文献:
http://www.inf.udec.cl/~leo/teoX.pdf
http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory