數據段(BSS段、DATA段)、代碼段(.RODATA)、堆棧段的區別

来源:http://www.cnblogs.com/-gebi-laowang/archive/2017/08/09/7325412.html
-Advertisement-
Play Games

聲明:本文為轉載的文章;並非由本人創作;發博文只是為了整理、記錄。 推薦的比較完全,比較清晰的文章(含圖):http://blog.csdn.net/sunny04/article/details/40627311 轉載時請註明出處和作者聯繫方式:http://blog.csdn.net/absur ...


聲明:本文為轉載的文章;並非由本人創作;發博文只是為了整理、記錄。

推薦的比較完全,比較清晰的文章(含圖):http://blog.csdn.net/sunny04/article/details/40627311

 

轉載時請註明出處和作者聯繫方式:http://blog.csdn.net/absurd

作者聯繫方式:李先靜 <xianjimli at hotmail dot com>

更新時間:2007-7-9

 

    全局變數是放在全局記憶體中的,但反過來卻未必成立。用static修飾的局部變數就是放在放全局記憶體的,它的作用域是局部的,但生命期是全局的。在有的嵌入式平臺中,堆實際上就是一個全局變數,它占用相當大的一塊記憶體,在運行時,把這塊記憶體進行二次分配。這裡我們並不強調全局變數和全局記憶體的差別。在本文中,全局強調的是它的生命期,而不是它的作用域,所以有時可能把兩者的概念互換。       一般來說,在一起定義的兩個全局變數,在記憶體的中位置是相鄰的。這是一個簡單的常識,但有時挺有用,如果一個全局變數被破壞了,不防先查查其前後相關變數的訪問代碼,看看是否存在越界訪問的可能。       在ELF(Executable and Linkable Format)格式的可執行文件中,全局記憶體包括三種:bss、data和rodata。其它可執行文件格式與之類似。瞭解了這三種數據的特點,我們才能充分發揮它們的長處,達到速度與空間的最優化。   數據段是包含了bss段和data段。   1.bss (Block Started by Symbol)段(bss segment)         又叫ZI(zero inital)段,通俗的說,bss是指那些沒有初始化的和初始化為0的全局變數         由原文的例子可見:bss類型的全局變數只占運行時的記憶體空間,而不占文件空間。 註:多數操作系統,在載入程式時,會把所有的bss全局變數全部清零,無需要你手工去清零。但為保證程式的可移植性,手工把這些變數初始化為0也是一個好習慣。   2.data(data segment)段      通俗的說,data指那些初始化過(非零)的非const的全局變數。如果數據全是零,為了優化考慮,編譯器把它當作bss處理。所以bss屬於一個特殊的data。       由原文的例子可見:data類型的全局變數是即占文件空間,又占用運行時記憶體空間的。   3.rodata       rodata的意義同樣明顯,ro代表read only,即只讀數據(const)。關於rodata類型的數據,要註意以下幾點:
         1.常量不一定就放在rodata里,有的立即數直接編碼在指令里,存放在代碼段(.text)中。
         2.對於字元串常量,編譯器會自動去掉重覆的字元串,保證一個字元串在一個可執行文件(EXE/SO)中只存在一份拷貝。
         3.rodata是在多個進程間是共用的,這可以提高空間利用率。
         4.在有的嵌入式系統中,rodata放在ROM(如norflash)里,運行時直接讀取ROM記憶體,無需要載入到RAM記憶體中。
         5.在嵌入式linux系統中,通過一種叫作XIP(就地執行)的技術,也可以直接讀取,而無需要載入到RAM記憶體中。
      由此可見,把在運行過程中不會改變的數據設為rodata類型的,是有很多好處的:在多個進程間共用,可以大大提高空間利用率,甚至不占用RAM空間。同時由於rodata在只讀的記憶體頁面(page)中,是受保護的,任何試圖對它的修改都會被及時發現,這可以幫助提高程式的穩定性。  

4.變數與關鍵字
static關鍵字用途太多,以致於讓新手模糊。不過,總結起來就有兩種作用,改變生命期和限製作用域。如:

         1.修飾inline函數:限製作用域
         2.修飾普通函數:限製作用域
         3.修飾局部變數:改變生命期
         4.修飾全局變數:限製作用域

const 關鍵字倒是比較明瞭,用const修飾的變數放在rodata里,字元串預設就是常量。對const,註意以下幾點就行了。
         1.指針常量:指向的數據是常量。如 const char* p = “abc”; p指向的內容是常量 ,但p本身不是常量,你可以讓p再指向”123”。(註:其中的“abc”是放在代碼段(.text)的,這個的格式也可以寫為   char const *p="abc";  )
         2.常量指針:指針本身是常量。如:char* const p = “abc”; p本身就是常量,你不能讓p再指向”123”。
         3.指針常量 + 常量指針:指針和指針指向的數據都是常量。const char* const p =”abc”; 兩者都是常量,不能再修改。

violatile關鍵字通常用來修飾多線程共用的全局變數和IO記憶體。告訴編譯器,不要把此類變數優化到寄存器中,每次都要老老實實的從記憶體中讀取,因為它們隨時都可能變化。這個關鍵字可能比較生僻,但千萬不要忘了它,否則一個錯誤讓你調試好幾天也得不到一點線索。

(註:這個相當於stm32文件中定義的__IO,代表了每次讀取用這個關鍵詞定義的值的時候,需要去記憶體中實時的讀取。也就是說每次得到的都是最新的值)

以下為補充:

轉載於:

http://blog.csdn.net/jxhui23/article/details/8064766

5.代碼段:

      代碼段(code segment/text segment)通常是指用來存放程式執行代碼的一塊記憶體區域。這部分區域的大小在程式運行前就已經確定,並且記憶體區域通常屬於只讀, 某些架構也允許代碼段為可寫,即允許修改程式。在代碼段中,也有可能包含一些只讀的常數變數,例如字元串常量等。

6.堆(heap):

      堆管理器是操作系統的一個模塊。是用於存放進程運行中被動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配記憶體時,新分配的記憶體就被動態添加到堆上(堆被擴張);當利用free等函數釋放記憶體時,被釋放的記憶體從堆中被剔除(堆被縮減)。

      堆的特點:

    需要手動申請(malloc)和釋放(free)

    臟記憶體,

    臨時性(在malloc和free之間能訪問)。

  (註:在測試的時候,堆free還能訪問其內部的記憶體,但是內部的記憶體值可能不正確了。)

    memset(p,0,10);//memset是對p當前位置後面的10個位元組賦予0的初值。通常用於清0。
    malloc返回的是一個void類型的指針。返回的值表示一個記憶體地址。失敗返回NULL。
    使用的過程:申請(malloc)->檢驗是否為空記憶體->使用申請的記憶體->釋放申請的記憶體(free(p))。

    malloc位於stdlib這個頭文件中。

    "程式泄露"又叫"吃記憶體"

    gcc(linux)中int malloc(0)其實不是沒有分配記憶體,它分配了0x10個記憶體;gcc預設返回最小16位元組的記憶體塊。

7.棧(stack)

      棧又稱堆棧, 是用戶存放程式臨時創建的局部變數,也就是說我們函數括弧“{}”中定義的變數(但不包括static聲明的變數,static意味著在數據段中存放變數)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值也會被存放回棧中。由於棧的先進後出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的記憶體區。

棧的特點:

     反覆使用,先進後出,臟記憶體,臨時性(函數不能返回棧變數的指針),棧會溢出。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 大數據時代,給想從事IT的人帶來了新的發展機會,也提供了新的職業發展通道。在面對眾多的大數據就業崗位,我們應該選擇什麼樣的職業發展方向 ...
  • 內置判斷,成功的時候返回0,不成功返回非零 test 判斷表達式 [ 判斷表達式 ] 註意前後必須留空格哦 數值運算 -eq 等於 -ne 不等於 -gt 大於 -ge 大於等於 -lt 小於 -le 小於等於 字元串運算 = 等於 != 不等於 -z 是否為空 -n 是否不為空 文件運算 -r 是 ...
  • Linux中Swap(即:交換分區),類似於Windows的虛擬記憶體,就是當記憶體不足的時候,把一部分硬碟空間虛擬成記憶體使用,從而解決記憶體容量不足的情況。swap分區在非高記憶體的伺服器上必不可少,但是swap不能充當記憶體使用。 一、swap分區擴展的方法 新建swap分區:以分區的形式創建swap 新 ...
  • IP地址:4段十進位,共32位二進位,如:192.168.1.1 二進位就是:11000000|10101000|00000001|00000001 子網掩碼可以看出有多少位是網路號,有多少位是主機號: 255.255.255.0 二進位是:11111111 11111111 11111111 00 ...
  • 一.系統管理與維護 1. pwd:print working directory 列印工作目錄 2. cd: change directory 改變或進入路徑 ● cd ~/ cd : 當前用戶目錄;回到主目錄(中間有空格!) ● cd /:根目錄; ● cd - :上一次訪問的目錄; ● cd .... ...
  • 原文發表於cu:2016-05-05 參考文檔: 一.環境 Server:CentOS-7-x86_64-1511 Client:Win7 x86_64, Chrome/Firefox瀏覽器 二.準備 1. iptables CentOS7預設自帶firewall,無iptables。 2. SEL ...
  • 如果你的伺服器的總是報告記憶體不足,並且時常因為記憶體不足而引發服務被強制kill的話,在不增加物理記憶體的情況下,啟用swap交換區作為虛擬記憶體是一個不錯的選擇,如果是SSD硬碟,正常讀寫速度都在300MB/s以上,啟用swap後性能提高了不少,特別是在處理消耗大記憶體的腳本方面。 ...
  • 0x00. Command Notation[Name] The name of the command.[Format] The code sequence. [ ]k indicates the contents of the [ ] s... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...