您的位置 首页 IOT

C言语程序内存分配

(1)内存分区状况栈区(stack):–分配,释放方式:由编译器自动分配和释放;–存放内容:局部变量,参数;–特点:具有后进先出

(1) 内存分区情况

栈区 (stack):

–分配, 开释方法: 由编译器主动分配 和 开释;

–寄存内容: 局部变量, 参数;

–特色: 具有 后进先出 特性, 合适用于 保存 回复 现场;

堆区 (heap):

–分配, 开释方法: 由程序员手动 分配(malloc) 和 开释(free), 假如程序员没有开释, 那么程序退出的时分, 会主动开释;

–寄存内容: 寄存程序运转中 动态分配 内存的数据;

–特色: 巨细不固定, 可能会动态的 扩展 或 缩小;

堆区内存请求:

–请求进程: OS中有一个记载闲暇内存地址的链表, 假如程序员请求内存, 就会找到空间大于请求内存巨细的节点, 将该节点从空间内存链表中删去, 并分配该节点;

–剩下内存处理: 体系会将剩下的部分从头放回 闲暇内存链表中;

–首地址记载巨细: 分配内存的首地址寄存该堆的巨细, 这样开释内存的时分才干正确履行;

大局区/静态区 (数据段 data segment /bss segment):

–分配, 开释方法: 编译器分配内存, 程序退出时体系主动开释内存;

–寄存内容: 大局变量, 静态变量;

–特色: 大局变量 和 静态变量存储在一个区域, 初始化的两种变量 和 未初始化的 存储在不同区域, 可是两个区域是相邻的;

常量区:

–分配, 开释方法: 退出程序由体系主动开释;

–寄存内容: 常量;

代码区 (text segment):

–分配, 开释方法: 编译器分配内存, 程序退出时体系主动开释内存;

–寄存内容: 寄存 程序的二进制代码, 和一些特别常量;

内存寄存次序 (由上到下): 栈区 -> 堆区 -> 大局区 -> 常量区 -> 代码区;

(2) 内存分配方法

大局内存分配:

–生命周期: 编译时分配内存, 程序退出后开释内存, 与 程序 的生命周期相同;

–存储内容: 大局变量, 静态变量;

栈内存分配:

–生命周期: 函数履行时分配内存, 履行完毕后开释内存;

–特色: 该分配运算由处理器处理, 功率高, 可是栈内存控件有限;

堆内存分配:

–生命周期: 调用 malloc()开端分配, 调用 free()开释内存, 完全由程序员操控;

–慎重运用: 假如分配了 没有开释, 会形成内存走漏, 假如频频 分配 开释 会呈现内存碎片;

(3) register变量

运用场景: 假如 一个变量运用频率特别高, 能够将这个变量放在 CPU 的寄存器中;

–润饰约束: 只要 局部变量 和 参数 能够被声明为 register变量, 大局 和 静态的不能够;

–数量约束: CPU 寄存器 很名贵, 不能界说太多register变量;

(4) extern 变量

extern变量概念: 声明外部变量, 外部变量就是在函数的外部界说的变量, 在本函数中运用;

–效果域: 从外部变量界说的方位开端, 知道本源码完毕都能够运用, 可是只能在界说extern后边运用, 前面的代码不能运用;

–寄存方位: 外部变量 寄存在 大局区;

extern变量效果: 运用extern润饰外部变量, ① 扩展外部变量在本文件中的效果域, ② 将外部变量效果域从一个文件中扩展到工程中的其它文件;

extern声明外部变量的情况:

–单个文件内声明: 假如不界说在文件最初, 其效果规模只能是 界说方位开端, 文件完毕方位完毕;

–多个文件中声明: 两个文件中用到一个外部变量, 只能界说一次, 编译 和 衔接的时分, 假如没有这个外部变量, 体系会知道这个外部变量在别处界说, 将另一个文件中的外部变量扩展到本文件中;

extern编译准则:

–本文件中能找到: 编译器遇到 extern 的时分, 现在本文件中找外部变量的界说的方位, 假如找到, 就将效果域扩展到 界说的方位 知道文件完毕;

–本文件中找不到: 假如本文件中找不到, 衔接其它文件找外部变量界说, 假如找到, 将外部变量效果域扩展到本文件中;

–外部文件找不到: 报错;

运用效果: extern 运用的时分, 能够不带数据类型;

–本文件: int A = 0; 在第10行, extern A 在榜首行, 那么A的效果域就扩展为从榜首行到文件结尾;

–多文件: 在任意文件中界说了 int A = 0; 在本文件中声明 extern A, 那么从当时方位到文件结尾都能够运用该变量;

(5) static变量 与 大局变量差异

static 变量 与 大局变量 相同点: 大局变量是静态存储的, 存储的方法 和 方位根本相同;

static 变量 与 大局变量不必点: 大局变量的效果域是 整个项目工程 横跨过个文件, 静态变量的效果域是 当时文件, 其它文件中运用是无效的;

变量存储方位: 大局变量 和 静态变量 寄存在 大局区/静态去, 局部变量寄存在 栈区(一般变量) 和 堆区(指针变量);

变量静态化:

–局部变量: 局部变量 加上 static , 相当于将局部变量的生命周期扩展到了整个文件, 效果域不改动;

–大局变量: 大局变量 加上 static , 相当于将大局变量的效果域缩小到了单个文件, 生命周期是整个程序的周期;

关于函数头文件的引申:

–内部函数: 单个文件中运用的内部函数, 仅在那个特定文件中界说函数即可;

–大局函数: 假如要在整个工程中运用一个大局函数, 需要将这个函数界说在一个头文件中;

static变量与一般变量差异:

–static大局变量 与 大局变量差异: static 大局变量 只初始化一次, 避免在其它文件中运用;

–static局部变量 与 局部变量差异: static 局部变量 只初始化一次, 下一次根据上一次成果;

static函数与一般函数差异: static 函数在内存中只保存一份, 一般函数 每调用一次, 就创立一个副本;

.

(6) 堆 和 栈比较

堆(heap)和栈(stack)差异:

–请求方法: stack 由体系主动分配, heap 由程序员进行分配;

–请求呼应: 假如 stack 没有满足的剩下空间, 就会溢出; 堆内存从链表中找闲暇内存;

–内存约束: stack 内存是接连的, 从高位向低位扩展, 并且很小, 只要几M, 是事前定好的, 在文件中装备; heap 是不接连的, 从低位向高位扩展, 体系是由链表操控闲暇程序, 链表从低地址到高地址, 堆巨细受虚拟内存约束, 一般32位机器有4G heap;

–请求功率: stack 由体系分配, 功率高; heap 由程序员分配, 速度慢, 简单发生碎片;

(7) 各区散布情况

.

依照下图散布: 由上到下次序 : 栈区(stack) -> 堆区(heap) -> 大局区 -> 字符常量区 -> 代码区;

验证分区情况:

–示例程序:

[cpp]view plaincopy

  1. /*************************************************************************
  2. >FileName:memory.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Mon10Mar201408:34:12PMCST
  6. ************************************************************************/
  7. #include
  8. #include
  9. intglobal1=0,global2=0,global3=0;
  10. voidfunction(void)
  11. {
  12. intlocal4=0,local5=0,local6=0;
  13. staticintstatic4=0,static5=0,static6=0;
  14. int*p2=(int*)malloc(sizeof(int));
  15. printf(“子函数局部变量:”);
  16. printf(“local4:%p”,&local4);
  17. printf(“local5:%p”,&local5);
  18. printf(“local6:%p”,&local6);
  19. printf(“子函数指针变量:”);
  20. printf(“p2:%p”,p2);
  21. printf(“大局变量:”);
  22. printf(“global1:%p”,&global1);
  23. printf(“global2:%p”,&global2);
  24. printf(“global3:%p”,&global3);
  25. printf(“子函数静态变量:”);
  26. printf(“static4:%p”,&static4);
  27. printf(“static5:%p”,&static5);
  28. printf(“static6:%p”,&static6);
  29. printf(“子函数地址:”);
  30. printf(“function:%p”,function);
  31. }
  32. intmain(intargc,char**argv)
  33. {
  34. intlocal1=0,local2=0,local3=0;
  35. staticintstatic1=0,static2=0,static3=0;
  36. int*p1=(int*)malloc(sizeof(int));
  37. constintconst1=0;
  38. char*char_p=”char”;
  39. printf(“主函数局部变量:”);
  40. printf(“local1:%p”,&local1);
  41. printf(“local2:%p”,&local2);
  42. printf(“local3:%p”,&local3);
  43. printf(“const1:%p”,&const1);
  44. printf(“主函数指针变量:”);
  45. printf(“p1:%p”,p1);
  46. printf(“大局变量:”);
  47. printf(“global1:%p”,&global1);
  48. printf(“global2:%p”,&global2);
  49. printf(“global3:%p”,&global3);
  50. printf(“主函数静态变量:”);
  51. printf(“static1:%p”,&static1);
  52. printf(“static2:%p”,&static2);
  53. printf(“static3:%p”,&static3);
  54. printf(“字符串常量:”);
  55. printf(“char_p:%p”,char_p);
  56. printf(“主函数地址:”);
  57. printf(“main:%p”,main);
  58. printf(“===============”);
  59. function();
  60. return0;
  61. }

–履行成果:

[cpp]view plaincopy

  1. [root@ip28pointer]#gccmemory.c
  2. [root@ip28pointer]#./a.out
  3. 主函数局部变量:
  4. local1:0x7fff75f5eedc
  5. local2:0x7fff75f5eed8
  6. local3:0x7fff75f5eed4
  7. const1:0x7fff75f5eed0
  8. 主函数指针变量:
  9. p1:0x19bad010
  10. 大局变量:
  11. global1:0x600e14
  12. global2:0x600e18
  13. global3:0x600e1c
  14. 主函数静态变量:
  15. static1:0x600e34
  16. static2:0x600e30
  17. static3:0x600e2c
  18. 字符串常量:
  19. char_p:0x4009f7
  20. 主函数地址:
  21. main:0x40065f
  22. ===============
  23. 子函数局部变量:
  24. local4:0x7fff75f5eea4
  25. local5:0x7fff75f5eea0
  26. local6:0x7fff75f5ee9c
  27. 子函数指针变量:
  28. p2:0x19bad030
  29. 大局变量:
  30. global1:0x600e14
  31. global2:0x600e18
  32. global3:0x600e1c
  33. 子函数静态变量:
  34. static4:0x600e28
  35. static5:0x600e24
  36. static6:0x600e20
  37. 子函数地址:
  38. function:0x400528

3. 指针与地址

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/iot/257189.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部