新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > C語(yǔ)言程序內(nèi)存分配

        C語(yǔ)言程序內(nèi)存分配

        作者: 時(shí)間:2016-11-27 來(lái)源:網(wǎng)絡(luò) 收藏

        (1) 內(nèi)存分區(qū)狀況

        本文引用地址:http://www.104case.com/article/201611/322296.htm

        棧區(qū) (stack):

        --分配, 釋放方式: 由編譯器自動(dòng)分配 和 釋放;

        --存放內(nèi)容: 局部變量, 參數(shù);

        --特點(diǎn): 具有 后進(jìn)先出 特性, 適合用于 保存 回復(fù) 現(xiàn)場(chǎng);

        堆區(qū) (heap):

        --分配, 釋放方式: 由程序員手動(dòng) 分配(malloc) 和 釋放(free), 如果程序員沒(méi)有釋放, 那么程序退出的時(shí)候, 會(huì)自動(dòng)釋放;

        --存放內(nèi)容: 存放程序運(yùn)行中 動(dòng)態(tài)分配 內(nèi)存的數(shù)據(jù);

        --特點(diǎn): 大小不固定, 可能會(huì)動(dòng)態(tài)的 放大 或 縮小;

        堆區(qū)內(nèi)存申請(qǐng):

        --申請(qǐng)過(guò)程: OS中有一個(gè)記錄空閑內(nèi)存地址的鏈表, 如果程序員申請(qǐng)內(nèi)存, 就會(huì)找到空間大于申請(qǐng)內(nèi)存大小的節(jié)點(diǎn), 將該節(jié)點(diǎn)從空間內(nèi)存鏈表中刪除, 并分配該節(jié)點(diǎn);

        --剩余內(nèi)存處理: 系統(tǒng)會(huì)將多余的部分重新放回 空閑內(nèi)存鏈表中;

        --首地址記錄大小: 分配內(nèi)存的首地址存放該堆的大小, 這樣釋放內(nèi)存的時(shí)候才能正確執(zhí)行;

        全局區(qū)/靜態(tài)區(qū) (數(shù)據(jù)段 data segment /bss segment):

        --分配, 釋放方式: 編譯器分配內(nèi)存, 程序退出時(shí)系統(tǒng)自動(dòng)釋放內(nèi)存;

        --存放內(nèi)容: 全局變量, 靜態(tài)變量;

        --特點(diǎn): 全局變量 和 靜態(tài)變量存儲(chǔ)在一個(gè)區(qū)域, 初始化的兩種變量 和 未初始化的 存儲(chǔ)在不同區(qū)域, 但是兩個(gè)區(qū)域是相鄰的;

        常量區(qū):

        --分配, 釋放方式: 退出程序由系統(tǒng)自動(dòng)釋放;

        --存放內(nèi)容: 常量;


        代碼區(qū) (text segment):

        --分配, 釋放方式: 編譯器分配內(nèi)存, 程序退出時(shí)系統(tǒng)自動(dòng)釋放內(nèi)存;

        --存放內(nèi)容: 存放 程序的二進(jìn)制代碼, 和一些特殊常量;

        內(nèi)存存放順序 (由上到下): 棧區(qū) -> 堆區(qū) -> 全局區(qū) -> 常量區(qū) -> 代碼區(qū);

        (2) 內(nèi)存分配方式

        全局內(nèi)存分配:

        --生命周期: 編譯時(shí)分配內(nèi)存, 程序退出后釋放內(nèi)存, 與 程序 的生命周期相同;

        --存儲(chǔ)內(nèi)容: 全局變量, 靜態(tài)變量;

        棧內(nèi)存分配:

        --生命周期: 函數(shù)執(zhí)行時(shí)分配內(nèi)存, 執(zhí)行結(jié)束后釋放內(nèi)存;

        --特點(diǎn): 該分配運(yùn)算由處理器處理, 效率高, 但是棧內(nèi)存控件有限;

        堆內(nèi)存分配:

        --生命周期: 調(diào)用 malloc()開始分配, 調(diào)用 free()釋放內(nèi)存, 完全由程序員控制;

        --謹(jǐn)慎使用: 如果分配了 沒(méi)有釋放, 會(huì)造成內(nèi)存泄露, 如果頻繁 分配 釋放 會(huì)出現(xiàn)內(nèi)存碎片;

        (3) register變量

        使用場(chǎng)景: 如果 一個(gè)變量使用頻率特別高, 可以將這個(gè)變量放在 CPU 的寄存器中;

        --修飾限制: 只有 局部變量 和 參數(shù) 可以被聲明為 register變量, 全局 和 靜態(tài)的不可以;

        --數(shù)量限制: CPU 寄存器 很寶貴, 不能定義太多register變量;

        (4) extern 變量

        extern變量概念: 聲明外部變量, 外部變量就是在函數(shù)的外部定義的變量, 在本函數(shù)中使用;

        --作用域: 從外部變量定義的位置開始, 知道本源碼結(jié)束都可以使用, 但是只能在定義extern后面使用, 前面的代碼不能使用;

        --存放位置: 外部變量 存放在 全局區(qū);

        extern變量作用: 使用extern修飾外部變量, ① 擴(kuò)展外部變量在本文件中的作用域, ② 將外部變量作用域從一個(gè)文件中擴(kuò)展到工程中的其它文件;

        extern聲明外部變量的情況:

        --單個(gè)文件內(nèi)聲明: 如果不定義在文件開頭, 其作用范圍只能是 定義位置開始, 文件結(jié)束位置結(jié)束;

        --多個(gè)文件中聲明: 兩個(gè)文件中用到一個(gè)外部變量, 只能定義一次, 編譯 和 連接的時(shí)候, 如果沒(méi)有這個(gè)外部變量, 系統(tǒng)會(huì)知道這個(gè)外部變量在別處定義, 將另一個(gè)文件中的外部變量擴(kuò)展到本文件中;

        extern編譯原則:

        --本文件中能找到: 編譯器遇到 extern 的時(shí)候, 現(xiàn)在本文件中找外部變量的定義的位置, 如果找到, 就將作用域擴(kuò)展到 定義的位置 知道文件結(jié)束;

        --本文件中找不到: 如果本文件中找不到, 連接其它文件找外部變量定義, 如果找到, 將外部變量作用域擴(kuò)展到本文件中;

        --外部文件找不到: 報(bào)錯(cuò);

        使用效果: extern 使用的時(shí)候, 可以不帶數(shù)據(jù)類型;

        --本文件: int A = 0; 在第10行, extern A 在第一行, 那么A的作用域就擴(kuò)展為從第一行到文件末尾;

        --多文件: 在任意文件中定義了 int A = 0; 在本文件中聲明 extern A, 那么從當(dāng)前位置到文件末尾都可以使用該變量;

        (5) static變量 與 全局變量區(qū)別

        static 變量 與 全局變量 相同點(diǎn): 全局變量是靜態(tài)存儲(chǔ)的, 存儲(chǔ)的方式 和 位置基本相同;

        static 變量 與 全局變量不用點(diǎn): 全局變量的作用域是 整個(gè)項(xiàng)目工程 橫跨過(guò)個(gè)文件, 靜態(tài)變量的作用域是 當(dāng)前文件, 其它文件中使用是無(wú)效的;

        變量存儲(chǔ)位置: 全局變量 和 靜態(tài)變量 存放在 全局區(qū)/靜態(tài)去, 局部變量存放在 棧區(qū)(普通變量) 和 堆區(qū)(指針變量);

        變量靜態(tài)化:

        --局部變量: 局部變量 加上 static , 相當(dāng)于將局部變量的生命周期擴(kuò)大到了整個(gè)文件, 作用域不改變;

        --全局變量: 全局變量 加上 static , 相當(dāng)于將全局變量的作用域縮小到了單個(gè)文件, 生命周期是整個(gè)程序的周期;

        關(guān)于函數(shù)頭文件的引申:

        --內(nèi)部函數(shù): 單個(gè)文件中使用的內(nèi)部函數(shù), 僅在那個(gè)特定文件中定義函數(shù)即可;

        --全局函數(shù): 如果要在整個(gè)工程中使用一個(gè)全局函數(shù), 需要將這個(gè)函數(shù)定義在一個(gè)頭文件中;

        static變量與普通變量區(qū)別:

        --static全局變量 與 全局變量區(qū)別: static 全局變量 只初始化一次, 防止在其它文件中使用;

        --static局部變量 與 局部變量區(qū)別: static 局部變量 只初始化一次, 下一次依據(jù)上一次結(jié)果;

        static函數(shù)與普通函數(shù)區(qū)別: static 函數(shù)在內(nèi)存中只保留一份, 普通函數(shù) 每調(diào)用一次, 就創(chuàng)建一個(gè)副本;

        .

        (6) 堆 和 棧比較

        堆(heap)和棧(stack)區(qū)別:

        --申請(qǐng)方式: stack 由系統(tǒng)自動(dòng)分配, heap 由程序員進(jìn)行分配;

        --申請(qǐng)響應(yīng): 如果 stack 沒(méi)有足夠的剩余空間, 就會(huì)溢出; 堆內(nèi)存從鏈表中找空閑內(nèi)存;

        --內(nèi)存限制: stack 內(nèi)存是連續(xù)的, 從高位向低位擴(kuò)展, 而且很小, 只有幾M, 是事先定好的, 在文件中配置; heap 是不連續(xù)的, 從低位向高位擴(kuò)展, 系統(tǒng)是由鏈表控制空閑程序, 鏈表從低地址到高地址, 堆大小受虛擬內(nèi)存限制, 一般32位機(jī)器有4G heap;

        --申請(qǐng)效率: stack 由系統(tǒng)分配, 效率高; heap 由程序員分配, 速度慢, 容易產(chǎn)生碎片;

        (7) 各區(qū)分布情況

        .

        按照下圖分布: 由上到下順序 : 棧區(qū)(stack) -> 堆區(qū)(heap) -> 全局區(qū) -> 字符常量區(qū) -> 代碼區(qū);

        驗(yàn)證分區(qū)狀況:

        --示例程序:

        [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("子函數(shù)局部變量:");
        16. printf("local4:%p",&local4);
        17. printf("local5:%p",&local5);
        18. printf("local6:%p",&local6);
        19. printf("子函數(shù)指針變量:");
        20. printf("p2:%p",p2);
        21. printf("全局變量:");
        22. printf("global1:%p",&global1);
        23. printf("global2:%p",&global2);
        24. printf("global3:%p",&global3);
        25. printf("子函數(shù)靜態(tài)變量:");
        26. printf("static4:%p",&static4);
        27. printf("static5:%p",&static5);
        28. printf("static6:%p",&static6);
        29. printf("子函數(shù)地址:");
        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("主函數(shù)局部變量:");
        40. printf("local1:%p",&local1);
        41. printf("local2:%p",&local2);
        42. printf("local3:%p",&local3);
        43. printf("const1:%p",&const1);
        44. printf("主函數(shù)指針變量:");
        45. printf("p1:%p",p1);
        46. printf("全局變量:");
        47. printf("global1:%p",&global1);
        48. printf("global2:%p",&global2);
        49. printf("global3:%p",&global3);
        50. printf("主函數(shù)靜態(tài)變量:");
        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("主函數(shù)地址:");
        57. printf("main:%p",main);
        58. printf("===============");
        59. function();
        60. return0;
        61. }


        --執(zhí)行結(jié)果:

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

        3. 指針與地址


        上一頁(yè) 1 2 下一頁(yè)

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 池州市| 红原县| 南安市| 旺苍县| 万州区| 莱西市| 井陉县| 疏勒县| 龙泉市| 建昌县| 宜城市| 开平市| 大宁县| 海门市| 仁寿县| 宕昌县| 尉犁县| 吐鲁番市| 东乡| 霍城县| 丁青县| 香格里拉县| 永定县| 大连市| 罗城| 临桂县| 扶沟县| 依安县| 乌兰浩特市| 锡林郭勒盟| 神木县| 南丹县| 扎鲁特旗| 砚山县| 马鞍山市| 贡嘎县| 乌苏市| 瑞金市| 通山县| 尼勒克县| 曲沃县|