C语言程序内存布局

如有转载,请注明出处:http://blog.csdn.net/embedded_sky/article/details/44457453

作者:super_bert@csdn

一、几个概念

1.栈(Stack)

C语言通过栈来维护函数调用上下文,也就是说C中的函数、函数参数列表、局部变量、函数返回值都保存在栈内存中,在完成函数调用之后栈帧随即销毁,至于具体的压栈顺序和上下文维护工作由谁来完成,则取决于函数的调用方式(cdecl/stdcall/fastcall/pascal).

关于C函数调用约定,或者叫调用惯例(Calling Convention),以下表格中,个人认为出栈方应该叫做栈的维护方更确切,表格:

详细请看这里

栈帧一般包括如下几方面内容:

①函数的参数列表和返回值(返回地址);

②临时变量:包括非静态局部变量和编译器自动生成的其他临时变量;

③保存的上下文:包括函数调用前后需保持不变的寄存器。

栈增长示意图

2.堆(Heap)

堆空间是需要程序自行申请的,简言之 在C语言程序中对空间由malloc函数族(malloc/alloc/calloc/realloc)申请,当然在C++中还有new关键字。堆空间由程序猿自行申请,也需由程序猿自行释放(此处,Javaer们笑看你们打脸)。malloc/free  new/delete分别对应申请和释放内存,new/delete是C++中的关键字,不是函数。

通常情况下比较好的做法是,free掉之后,立即将指针置为NULL,因为通常if语句只会去判断指针是否为NULL(0x00000000),堆空间(内存)在free掉之后,该指针并不会指向NULL,也就是说free掉的是内存而不是指针,如果程序之后又用到该指针,后果将是不可预知的。如果被置为NULL,则可以被if语句检测出来,防止自己给自己留坑,C中的坑已经够多的了。

glibc中的malloc函数是这样处理用户堆空间请求的:

①对于小于128KB的请求,在现有的堆空间里,按照分配算法为他分配一块空间并返回;

②对于大于128KB的请求,malloc内部会调用mmap()函数分配一块匿名空间,然后在这块匿名空间中为用户分配空间。

mmap函数的具体用法请参考Linux  manpage,Windows环境下是没有mmap函数的,malloc函数族应该是依赖于 VirtualAlloc()函数申请堆空间。

3.动态链接库(Dynamic Libraries)

Linux/Unix环境下应该是***.so之类的文件,Windows下则是DLL(Dynamic Linking Libraries)。

二、Linux进程地址空间

先上图,箭头代表stack和heap的增长方向,dynamic libraries在2.4和2.6以后的内核中装载位置不一样,分别为0x40000000,0xBFXXXXXX.

Linux采用了分页的内存管理机制。由于x86体系的分页机制是基于分段机制的,因此,为了使用分页机制,分段机制是无法避免的。为了降低复杂性,Linux内核将所有段的基址都设为0,段限长设为4G,只是在段类型和段访问权限上有所区分,并且Linux内核和所有进程共享1个GDT,不使用LDT(即系统中所有的段描述符都保存在同一个GDT中),这是为了应付CPU的分段机制所能做的最少工作。

Linux内存管理机制可以分为3个层次,从下而上依次为物理内存的管理、页表的管理、虚拟内存的管理。

三、Windows进程地址空间

相较Linux而言,Windows环境下的进程空间布局就显得"支离破碎",

各位看官么看完这图估计会有点奇怪,一开始我也奇怪,为啥会有那么多stack呢?上面有说到,栈用于维护函数调用上下文,一个进程中调用函数所需存储的参数/变量/返回值,哪用得了那么多栈内存。

造成需要这么多栈内存的原因如下,每个线程的栈空间都是独立的,而Windows程序一般都是多线程,很大一部分原因Windows的进程耗费资源太大,线程优化得比*nix要好得多。试想一下,若在一个进程中通过CreateThread创建了多个线程,然后每个线程的栈空间都是独立的,且可以通过CreateThread API的参数来指定(系统默认的每个线程栈大小为1M byte),所以一旦程序起起来,内存空间已经支离破碎了。

然而我们的应用程序得在这个支离破碎的内存空间中去malloc堆(heap)空间,VirtualAlloc().

malloc函数族在Windows环境下最终依赖于VirtualAlloc()函数实现,而VirtualAlloc()函数像操作系统申请的空间必须是页大小的整数倍,也就是说对于x86系统一次性申请的heap最少是4096个byte,OS就是这么定的。但是OS还提供了一个堆管理器,堆管理器每次向OS申请一大片heap空间,然后在申请到的空间里给应用程序进行malloc。

HeapCreate创建一个堆;

HeapAlloc从堆空间中申请内存;

HeapFree释放内存;

HeapDestroy销毁一个堆;

相当于咱们从冷库里一次性批发了一箱冰激凌放在家里,咱们想吃的时候就一个一个去冰箱拿,想吃几个就拿几个。

此文只是抛砖引玉,其中很多地方都值得深入去研究、理解。

参考:http://www.cnblogs.com/zszmhd/archive/2012/08/29/2661461.html

x64系统程序内存布局请参考:http://blog.chinaunix.net/uid-27119491-id-3325943.html

C语言程序内存布局的更多相关文章

  1. 一起talk C栗子吧(第一百三十一回:C语言实例--C程序内存布局三)

    各位看官们,大家好.上一回中咱们说的是C程序内存布局的样例,这一回咱们继续说该样例.闲话休提,言归正转.让我们一起talk C栗子吧. 看官们,关于C程序内存布局的样例,我们在前面的两个章回都介绍过了 ...

  2. C语言程序内存的分区

    本文转载自:https://blog.csdn.net/shulianghan/article/details/20472269 C语言程序内存分配 (1) 内存分区状况 栈区 (stack) :  ...

  3. 用一个词(TASPK)牢记C程序内存布局

    一个典型的C程序内存布局,从低地址到高地址分别为: 1. text (正文段,即代码段 Code Segment) 2. data (已经初始化的数据段) 3. bss (未被初始化的数据段 Bloc ...

  4. C程序内存布局

    作为计算机专业的来说,程序入门基本都是从C语言开始的,了解C程序中的内存布局,对我们了解整个程序运行,分析程序出错原因,会起到事半功倍的作用 . C程序的内存布局包含五个段,分别是STACK(栈段), ...

  5. C++程序内存布局

      代码区(code area) 程序内存空间 全局数据区(data area) 堆区(heap area) 栈区(stack area) 一个由C/C++编译的程序占用的内存分为以下几个部分, 1) ...

  6. C语言程序内存分布

     一个进程的数据在内存中的布局如下图: bss段(bss segment):可读可写不可执行,通常用来存放程序中未初始化的全局变量.bss是英文Block Started by Symbol的简称.b ...

  7. linux C 程序内存布局

    参考: 1. http://www.cnblogs.com/clover-toeic/p/3754433.html 2. http://www.cnblogs.com/jacksu-tencent/p ...

  8. ESP32应用程序的内存布局

    应用程序内存布局 ESP32芯片具有灵活的内存映射功能.本节介绍ESP-IDF在默认情况下如何使用这些功能. ESP-IDF中的应用程序代码可以放置在以下内存区域之一中. IRAM(指令RAM) ES ...

  9. c++内存布局与c程序的内存布局

    c/c++的内存布局:堆,栈,自由存储区(与堆的区别),全局/静态存储区,常量存储区(字符串常量,const常量) http://www.cnblogs.com/QG-whz/p/5060894.ht ...

随机推荐

  1. Maven(六)之依赖管理

    前面讲了maven一些关于Maven的简单知识,今天我给大家分享一些Maven的依赖管理.我相信用过maven的人都知道,它很重要的功能就是通过依赖来添加jar包. 让我们领略一下Maven是怎么管理 ...

  2. Spark组件

    1,Application application(应用)其实就是用spark-submit提交的程序.比方说spark examples中的计算pi的SparkPi.一个application通常包 ...

  3. 风趣的JavaScript面向对象入门课程一

    在我们程序猿界一直流传这这么一个joke,没女票我们可以new一个.没房子没票子没车子我们同样new一个!当然这听着更像是一种自嘲,毕竟我们程序猿都爱自嘲,哈哈,废话不多说,今天就由我带着你们来入Ja ...

  4. 无限树Jquery插件zTree的使用方法

    其实Ztree官网已经有详细的API文档,一切以官网上的说明为准,我在此只是结合实践总结几条常用的ztree的功能特性. (ztree的语法结构是基于key-value的形式配置) 1:支持异步加载数 ...

  5. Java EE开发环境——MyEclipse2017破解 和 Tomcat服务器配置

    Java EE开发,我们可以搭建如下开发环境: 底层运行环境:jdk 和 jre. Web服务器:Tomcat 后台数据库:SQL Server 可视化集成开发环境:MyEclipse Java EE ...

  6. Average of Levels in Binary Tree

    Given a non-empty binary tree, return the average value of the nodes on each level in the form of an ...

  7. Nginx平滑升级源码分析

    一.平滑升级步骤 1.重命名之前的sbin/nginx文件,将新的nginx文件放到sbin/目录下 #mv ./sbin/nginx ./sbin/nginx.old #cp ~/nginx ./s ...

  8. win2003服务器定时自动重启命令

    1. win2003可以这样自动重启: 新建一个命令行文件比如reboot.bat 内容如下:shutdown -r -t 30 在计划任务中新建一个任务,程序选择上面这个reboot.cmd文件,时 ...

  9. java spark-streaming接收TCP/Kafka数据

    本文将展示 1.如何使用spark-streaming接入TCP数据并进行过滤: 2.如何使用spark-streaming接入TCP数据并进行wordcount: 内容如下: 1.使用maven,先 ...

  10. nginx + keepalived 实现高可靠web网站

    组网图: 配置信息: 左边nigx 服务器的 /usr/local/nginx/conf/nginx.conf #user  nobody; worker_processes  1; #error_l ...