「iOS」——內存五大分區

UI學習

  • iOS-底層原理 24:內存五大區
        • 總覽
      • 一、棧區(Stack)
        • 1.1 核心特性
        • 1.2 優缺點
        • 1.3函數棧與棧幀
        • 1.3 堆棧溢出風險
      • 二、堆區(Heap);
        • 2.1 核心特性
        • 2.2 與棧區對比
      • 三、全局 / 靜態區(Global/Static)
        • 3.1 內存劃分
        • 3.2 關鍵區別
      • 四、常量區(Constant)
      • 五、代碼區(Code/Text)
      • 面試問題學習;
        • 問題 1:`static`關鍵字的作用
        • 問題 2:堆內存碎片如何產生?
        • 問題3:請簡述iOS應用程序的五大內存分區及其主要用途。
        • 問題4:為什么棧內存的分配和釋放速度比堆內存快?
        • 問題5:全局區和靜態區的內存是如何管理的?它們之間有什么區別? 有問題
      • 總結:內存分區速查表


iOS-底層原理 24:內存五大區

總覽

iOS 中,內存主要分為五大區域:棧區、堆區、全局區 / 靜態區、常量區和代碼區。內存布局總覽如下:

請添加圖片描述

由低地址到高地址依次為 代碼區→常量區→全局 / 靜態區→堆區→棧區,內核區位于最高地址。

一、棧區(Stack)

1.1 核心特性
  • 存儲方向:從高地址向低地址分配,內存連續。

  • 管理方式:系統自動分配 / 釋放(函數結束后立即回收)。

  • 典型存儲:局部變量、方法參數(如self_cmd)、函數返回地址。

  • 地址特征:iOS 中以0X70X16開頭。

示例代碼

- (void)testStack {  int a = 10;  NSLog(@"a == %p size == %lu", &a, sizeof(a));  NSLog(@"方法參數 self:%p", &self);  NSLog(@"方法參數 cmd:%p", &_cmd);  
}  

輸出結果

請添加圖片描述

地址從0x16fdff2a8(self)→0x16fdff2a0(cmd)→0x16fdff29c(a),由高到低遞減,步長 8 字節,驗證棧的「后進先出」特性。

1.2 優缺點
  • 優點:速度快(系統自動管理)、無內存碎片。

  • 缺點:空間受限(iOS 主線程棧大小 1MB,其他線程 512KB)。

1.3函數棧與棧幀

棧幀定義
函數運行時在棧區分配的獨立連續內存區域,包含:

  • 局部變量:函數內定義的變量(如int z = x + y;)。
  • 調用記錄:返回地址(LR)、當前函數指針(PC)、棧基址(FP)、棧指針(SP)等。
  • 參數傳遞:函數參數通過棧幀傳遞(如Add(a, b)中的ab)。

函數調用流程

  1. 壓棧

    :調用函數時,系統創建新棧幀,將參數、局部變量、PC/LR 等壓入棧區。

    • 例:main函數調用Add(a, b)時,先壓入ab,再壓入Add函數的棧幀。
  2. 執行:函數在棧幀內執行,操作局部變量(如計算z = x + y)。

  3. 出棧:函數執行完畢,棧幀出棧,釋放內存,程序通過 LR 返回調用處(如從Add返回main)。

- (void)testStackFrame {  int a = 10;  int b = 20;  int sum = [self addWithA:a b:b];  NSLog(@"sum = %d", sum);  
}  - (int)addWithA:(int)a b:(int)b {  return a + b;  
}  

棧幀變化

  1. testStackFrame調用時,棧幀壓入absum等局部變量。
  2. 調用addWithA:b:時,新棧幀壓入參數ab,計算后通過 LR 返回結果。
  3. 函數結束后,兩層棧幀依次出棧,釋放內存。
1.3 堆棧溢出風險
  • 棧溢出:
    • 原因:遞歸深度過深(如無限遞歸)或局部變量過多,超過棧空間限制(如主線程 1MB)。
    • 后果:程序崩潰,拋出EXC_BAD_ACCESS異常。
  • 堆溢出:
    • 原因:頻繁分配大內存(如循環創建未釋放的對象),耗盡虛擬內存。
    • 后果:內存不足,系統終止進程。

二、堆區(Heap);

2.1 核心特性
  • 存儲方向:從低地址向高地址分配,內存不連續(基于鏈表管理)。

  • 管理方式:手動分配 / 釋放(alloc/free等),需避免內存泄漏。

  • 典型存儲:OC 對象([NSObject new])、動態分配的數據(malloc)。

  • 地址特征:iOS 中以0x6開頭。

示例代碼

- (void)testHeap {  NSObject *object1 = [NSObject new];  NSObject *object2 = [NSObject new];  NSLog(@"object1 = %@", object1);  NSLog(@"object2 = %@", object2);  
}  

輸出結果

請添加圖片描述

地址0x6000029ac0700x6000029ac080不連續,驗證堆的「非連續分配」特性。

2.2 與棧區對比
維度棧區堆區
分配方式 系統自動(LIFO) 手動分配(鏈表遍歷)
內存連續性 連續 不連續
生命周期 函數作用域內 手動釋放或程序結束
空間大小 受限(1MB/512KB) 受限于虛擬內存
碎片問題 易產生

三、全局 / 靜態區(Global/Static)

3.1 內存劃分
  • .bss 段:存儲未初始化的全局變量和靜態變量,程序啟動時自動清零。

  • .data 段:存儲已初始化的全局變量和靜態變量

示例代碼

int globalVar;          // 未初始化全局變量(.bss)  
static int staticVar;   // 未初始化靜態變量(.bss)  
int initGlobal = 10;    // 已初始化全局變量(.data)  
static int initStatic = 11; // 已初始化靜態變量(.data)  - (void)testStatic {  NSLog(@"globalVar = %p", &globalVar);  NSLog(@"staticVar = %p", &staticVar);  NSLog(@"initGlobal = %p", &initGlobal);  NSLog(@"initStatic = %p", &initStatic);  
}  

輸出結果

請添加圖片描述

分析

  • .bss段地址連續(0x1000081000x10008104,相差 4 字節)。

  • .data段地址連續(0x1000080f80x1000080fc,相差 4 字節)。

3.2 關鍵區別
類型作用域初始化時機
全局變量 全程序可見 程序啟動時分配
靜態全局變量 當前文件可見 程序啟動時分配
靜態局部變量 函數內可見 第一次調用時分配

四、常量區(Constant)

  • 存儲內容:字符串常量(如@"Hello")、基本類型常量(如1233.14)。

  • 特性

    • 只讀,程序運行時不可修改。
    • 編譯時分配,程序結束后由系統釋放。

五、代碼區(Code/Text)

  • 存儲內容:編譯后的二進制指令(函數體、方法實現)。

  • 特性

    • 只讀,防止程序運行中意外修改代碼。

    • 共享性:相同程序的多個實例共享代碼區(如多個 App 進程共享系統庫代碼)。

    • 安全意義:阻止惡意代碼注入和篡改,防御緩沖區溢出攻擊。

面試問題學習;

問題 1:static關鍵字的作用
  • 對于全局變量來說,static 改變了其作用域。普通全局變量是所有文件都可以用。靜態全局變量是只有當前文件可以用。
  • 對于局部變量來說,static改變了其存儲方式從而改變了生命周期。普通局部變量是動態存儲,動態存儲決定了其生命周期為變量使用期間。靜態局部變量是靜態存儲,存儲在全局靜態區,生命周期為從程序開始到結束。
  • 因此 static 這個說明符在不同的地方所起的作用是不同的。
  • 總結:全局變量、靜態全局變量、靜態局部變量采用靜態存儲方式,局部變量采用動態存儲方式。
問題 2:堆內存碎片如何產生?
  • 原因:頻繁分配 / 釋放不同大小的內存塊,導致空閑內存碎片化(如分配 100 字節→釋放→分配 20 字節→釋放,留下 80 字節小塊無法被大內存請求利用)。

  • iOS 優化方案

    • 使用 ARC 自動管理內存,減少手動操作。
      
    • 對象池技術(如`NSOperationQueue`復用線程)。
      
    • 避免高頻小內存分配(如改用緩存機制)。
      
問題3:請簡述iOS應用程序的五大內存分區及其主要用途。
  1. 棧(Stack)

    • 用途:用于存儲局部變量、函數參數、返回地址等。棧內存是自動分配和釋放的,主要用于函數調用和局部變量的管理。
    • 特點:內存分配方式為LIFO(后進先出),存取速度快,空間相對較小。
  2. 堆(Heap)

    • 用途:用于動態分配內存,存儲需要在運行時分配和釋放的對象和數據。堆內存由程序員手動管理,通過mallocfreenewdelete等函數進行分配和釋放。
    • 特點:內存管理靈活,存儲空間較大,但分配和釋放速度相對較慢,容易產生內存碎片。
  3. 全局區/靜態區(Global/Static)

    • 用途:存儲全局變量和靜態變量。全局變量在程序啟動時分配,在程序結束時釋放;靜態變量在第一次使用時分配,程序結束時釋放。
    • 特點:內存地址固定,生命周期貫穿程序運行的整個周期。
  4. 常量區(Constant)

    • 用途:存儲常量數據,例如字符串常量、數值常量等。常量區的內容在程序運行時不可修改。
    • 特點:只讀區域,數據在程序加載時初始化,生命周期貫穿程序運行的整個周期。
  5. 代碼區(Code/Text)

    • 用途:存儲程序的可執行代碼,包括函數體和編譯后的指令。代碼區在程序運行時是只讀的,以防止意外修改。
    • 特點:只讀區域,存儲的是編譯后的機器指令,生命周期貫穿程序運行的整個周期。
問題4:為什么棧內存的分配和釋放速度比堆內存快?
  1. 分配方式:棧內存采用LIFO(后進先出)的分配方式,每次函數調用時,函數的局部變量、參數和返回地址會依次入棧,函數返回時,這些數據會依次出棧。分配和釋放只需要移動棧指針,操作簡單且高效。
  2. 內存管理:棧內存由系統自動管理,函數調用結束時,系統會自動釋放棧內存,無需程序員手動管理。堆內存則需要程序員手動管理,通過mallocfree等函數進行分配和釋放,管理復雜且容易產生內存碎片。
  3. 空間連續:棧內存通常是連續的內存塊,分配和釋放時不需要進行復雜的內存碎片整理,而堆內存由于頻繁的分配和釋放,容易產生內存碎片,導致分配和釋放速度變慢。
問題5:全局區和靜態區的內存是如何管理的?它們之間有什么區別? 有問題
  • 全局區(Global)

    • 管理全局變量,即在程序的整個生命周期內都存在的變量。這些變量在程序啟動時分配內存,在程序結束時釋放內存。
    • 全局變量在定義時如果未顯式初始化,系統會將其初始化為0。
  • 靜態區(Static)

    • 管理靜態變量,即在函數或類內部定義并帶有static關鍵字的變量。這些變量在第一次使用時分配內存,在程序結束時釋放內存。
    • 靜態變量在第一次定義時如果未顯式初始化,系統也會將其初始化為0。

區別

  • 生命周期:全局變量和靜態變量的生命周期相似,都是在程序運行期間存在,但全局變量在程序啟動時即被初始化,而靜態變量在第一次使用時才被初始化。
  • 作用域:全局變量的作用域是整個程序,而靜態變量的作用域僅限于其定義的函數或類內部。

總結:內存分區速查表

分區地址方向 讀寫權限 管理方式 典型存儲
棧區 高→低 可讀可寫 系統自動 局部變量、函數參數
堆區 低→高 可讀可寫 手動分配 OC 對象、動態數據
全局 / 靜態區 固定 可讀可寫 編譯時分配 全局變量、靜態變量
常量區 固定 只讀 編譯時分配 字符串、數值常量
代碼區 固定 只讀 編譯時分配 可執行指令

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92931.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92931.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92931.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每日一題【刪除有序數組中的重復項 II】

刪除有序數組中的重復項 II思路class Solution { public:int removeDuplicates(vector<int>& nums) {if(nums.size()<2){return nums.size();}int index 2;for (int i 2; i < nums.size();i ) {if(nums[i] ! nums[index-2]) {nums[index]nums[i];}}return ind…

兼容性問題記錄

1、dialog設置高度MATCH_PARENT全屏后&#xff0c;三星機型和好像是一加&#xff0c;會帶出頂部狀態欄&#xff0c;設置隱藏狀態欄屬性無效。解決方法&#xff1a;高度不設置為MATCH_PARENT&#xff0c;通過windowmanager.getdefaultdisplay來獲取并設置高度&#xff0c;再設置…

6.數組和字符串

在C語言中&#xff0c;數組和字符串是基礎且重要的概念。它們用于存儲和操作一系列相同類型的元素或字符序列。數組1. 數組定義與初始化數組是一系列相同類型的數據項的集合&#xff0c;這些數據項可以通過一個共同的名字來引用。數組中的每個元素都有一個索引&#xff08;也稱…

odoo代碼分析(一)

Odoo 是一套基于網絡的開放式源代碼商業應用套件,既可以作為獨立應用運行,也可以作為集成的全功能 ERP 系統使用。Odoo 平臺采用模塊化架構,允許組織根據自身需求起步,并在需求增長時擴展功能。 什么是 Odoo? Odoo 提供了一個完整的商業應用生態系統,包括: 客戶關系管…

從“人工眼”到‘智能眼’:EZ-Vision視覺系統如何重構生產線視覺檢測精度?

制造業是我國實體經濟的基礎&#xff0c;是國內經濟增長的重要引擎。制造業智能化建設是當下的必然趨勢&#xff0c;然而目前依舊有很多中小型企業因為成本原因&#xff0c;無法加快智能化制造的步伐。在智能檢測領域更是如此&#xff0c;很多企業依舊在采用人工檢測&#xff0…

Etcd原理基礎學習

etcd 是一個開源的分布式鍵值存儲系統&#xff0c;專注于提供高可用性、強一致性的數據存儲與訪問&#xff0c;廣泛應用于分布式系統的服務發現、配置管理和協調任務。以下是其核心特性和應用場景的詳細介紹。接下來就看看Etcd如何實現服務注冊&#xff0c;以及如何通過Raft算法…

【硬件-筆試面試題】硬件/電子工程師,筆試面試題-32,(知識點:模數轉換器,信噪比,計算公式,)

目錄 1、題目 2、解答 步驟一&#xff1a;明確理想 ADC 的信噪比公式 步驟二&#xff1a;推導公式的來源 步驟三&#xff1a;得出答案 3、相關知識點 一、信噪比&#xff08;SNR&#xff09;的定義 二、理想 ADC 的量化噪聲 三、滿量程正弦波信號的功率 四、信噪比公…

Redis過期數據的刪除策略是什么?有哪些?

定時刪除&#xff1a;- 每個設置了TTL的key中都會創建一個計時器&#xff0c;等到過期時間就會立即刪除- 對內存友好&#xff0c;但是會占用大量的CPU資源去處理過期數據&#xff0c;從而影響緩存的吞吐量和響應時間惰性刪除&#xff1a;- 設置了key的過期后&#xff0c;不會立…

linux dd命令詳解

dd 是一個功能強大的 Unix/Linux 命令行工具&#xff0c;用于低級別的字節流操作&#xff0c;常用于創建、復制、轉換和處理文件或設備數據。它在 macOS 和 Linux 系統上都可用&#xff0c;但在 macOS 上有一些細微差異。本文將詳細講解 dd 命令的用法&#xff0c;包括參數、常…

多線程同步技術是用于協調多個線程訪問共享資源或執行順序的機制,以避免數據競爭、死鎖、線程不安全等問題

多線程同步技術是用于協調多個線程訪問共享資源或執行順序的機制,以避免數據競爭、死鎖、線程不安全等問題。 在提供的代碼中,存在多線程操作加熱板的場景,涉及鎖競爭和硬件資源訪問,優化多線程同步可以顯著提升程序性能和穩定性。 以下是多線程同步技術的詳細解釋、常見…

CRMEB標準版,從創建數據表到實現最基礎增刪改查的實現過程

很多使用了CRMEB單商戶系統的童鞋在進行二開的時候&#xff0c;都會遇到新建了數據表之后不知道對數據表怎么進行操作。那么&#xff0c;這篇文章將帶你完整的實現一遍&#xff0c;以后就不會怕啦。一、創建數據表就以最簡單的為例&#xff0c;創建一個學生的信息表編號姓名性別…

J2EE模式---數據訪問對象模式

數據訪問對象模式基礎概念數據訪問對象模式&#xff08;Data Access Object Pattern&#xff0c;簡稱 DAO 模式&#xff09;是一種結構型設計模式&#xff0c;其核心思想是將數據訪問邏輯與業務邏輯分離&#xff0c;通過一個抽象層&#xff08;DAO&#xff09;來處理數據的持久…

【OpenCV篇】OpenCV——02day.圖像預處理(1)

目錄 前言 一、圖像色彩空間轉換 1 RGB顏色空間 2 顏色加法 3 顏色加權加法 4 HSV顏色空間 5 RGB轉Gray(灰度) 二、灰度實驗 1 灰度圖 2 最大值法 3 平均值法 4 加權均值法 5 兩個極端的灰度值 三、圖像二值化處理 二值圖像 1 閾值法(THRESH_BINARY) 2 反閾值…

經典IDE之Turbo C

寫的程序不多&#xff0c;換過的 IDE 不少&#xff0c;本文將列舉曾經用過的不同 C 語言相關的 IDE 環境&#xff0c;既是紀念&#xff0c;也是回憶。值得注意的是 IDE 的出現是為了提高開發效率&#xff0c;有一個相對成熟的編譯環境和程序。從編程的角度來看&#xff0c;過分…

Go 多模塊倉庫標簽管理教程

為了方便自己開發&#xff0c;自己寫了個小工具&#xff1a;DzhGO 代碼生成工具 功能特點標題 初始化項目基礎結構生成插件模塊代碼生成模型和實體代碼生成服務接口和實現代碼支持 admin 和 app 兩種模塊類型生成項目基礎目錄 具體介紹看倉庫&#xff1a; https://github.co…

IDEA 類上方注釋 簽名

File -->settings–>Editor–>File and Code Templates–>class新建 Class 類上方添加內容&#xff1a;/*** author Jagger* since ${DATE} ${TIME}*/

衛星通信終端天線對星之:參考星對星

我們在前面的文章中介紹了3種衛星通信終端的對星模式&#xff0c;分別是&#xff1a; 衛星通信終端天線的5種對星模式之一&#xff1a;信標跟蹤 衛星通信終端天線的5種對星模式之二&#xff1a;功率檢測型載波跟蹤 衛星通信終端天線的5種對星模式之二&#xff1a;DVB跟蹤 今…

來自麻省理工和AI制藥公司 Recursion 的結構與結合親和力預測模型Boltz-2,解決小分子藥物發現的關鍵問題

1. Boltz-2介紹 文章來源&#xff1a;http://jeremywohlwend.com/assets/boltz2.pdf 開源代碼來源&#xff1a;https://github.com/jwohlwend/boltz 該AI模型由麻省理工學院計算機科學與人工智能實驗室與上市AI制藥公司Recursion一起開發&#xff0c;雙方在Boltz-1的基礎之上…

從零用java實現 小紅書 springboot vue uniapp(14) 集成阿里云短信驗證碼

從零用java實現 小紅書 springboot vue uniapp&#xff08;14&#xff09; 集成阿里云短信驗證碼 移動端演示 http://8.146.211.120:8081/#/ 管理端演示 http://8.146.211.120:8088/#/ 項目整體介紹及演示 前言 在現代應用中&#xff0c;手機號不僅是用戶的唯一標識&#xff0…

`<< EOF` 與 `<< ‘EOF‘` 與 `<< “EOF“`有無引號的區別多回答筆記250722

<< EOF 與 << EOF 與 << "EOF"有無引號的區別多回答筆記250722 實測 自測代碼: # 定義變量 hello"ni hao"# 無引號 tee << EOF # 無引號 ${hello} world \n $(date) # 無引號 EOF# 單引號 tee << EOF # 單…