[iOS]內存分區

[iOS]內存分區

文章目錄

  • [iOS]內存分區
    • 五大分區
      • 棧區
      • 堆區
      • 全局區
      • 常量區
      • 代碼區
      • 驗證
      • 內存使用注意事項
      • 總結
    • 函數棧
      • 堆棧溢出
      • 棧的作用
    • 參考博客

在iOS中,內存主要分為棧區、堆區、全局區、常量區、代碼區五大區域
還記得OC是C的超類
所以C的內存分區也是一樣的

iOS系統中,應用的虛擬內存默認分配4G大小,但五大區只占3G,還有1G是五大區之外的內核區

上圖

在這里插入圖片描述

五大分區

棧區

定義

  • 棧是系統數據結構,其 對應的進程或者線程是唯一
  • 棧是 向低地址擴展 的數據結構
  • 棧是一塊連續的內存區域,遵循 先進后出(FILO) 原則
  • 棧的地址空間在iOS中是以 0X7或者0X16開頭
  • 棧區一般在 運行時分配

存儲
棧區是由編譯器 自動分配并釋放 的,主要用來存儲

  • 局部變量
  • 函數的參數,例如函數的隱藏參數(id self,SEL _cmd)

優缺

優點:因為棧是由編譯器自動分配并釋放的,不會產生內存碎片,所以快速高效

缺點:棧的內存大小有限制,數據不靈活

  • OS X(MAC上)主線程棧大小是8MB
  • iOS主線程棧大小是1MB
  • 其他線程是512KB
    在這里插入圖片描述

堆區

定義

  • 堆是 向高地址擴展 的數據結構
  • 堆是 不連續 的內存區域,類似于鏈表結構(便于增刪,不便于查詢),遵循先進先出 (FIFO) 原則
  • 堆的地址空間在iOS中是以 0x6 開頭,其空間的分配總是動態的
  • 堆區的分配一般是在 運行時分配

儲存
堆區是由程序員動態分配和釋放的,如果程序員不釋放,程序結束后,可能由操作系統回收,主要用于存放

  • OC中使用alloc或者 使用new開辟空間創建對象
  • C語言中使用malloc、calloc、realloc分配的空間,需要free釋放

優缺
優點:靈活方便,數據適應面廣泛

缺點:需手動管理,速度慢、容易產生內存碎片
當需要訪問堆中內存時,一般需要先 通過對象讀取到棧區的指針地址 ,然后通過 指針地址 訪問堆區

全局區

  • 全局區是編譯時分配的內存空間
  • 在iOS中一般以 0x1 開頭
  • 在程序運行過程中,此內存中的數據一直存在,程序結束后由系統釋放,主要存放
    1. 未初始化的全局變量和靜態變量,即BSS區(.bss)
    2. 已初始化的全局變量和靜態變量,即數據區(.data)
      BBS:Block Started by Symbol

其中,全局變量是指變量值可以在運行時被動態修改,而靜態變量是static修飾的變量,包含靜態局部變量和靜態全局變量

常量區

常量區(.rodata)是 編譯時分配 的內存空間,在程序結束后由系統釋放,主要存放

  • 已經使用了的,且沒有指向的字符串常量
    字符串常量因為可能在程序中被多次使用,所以在程序運行之前就會提前分配內存

代碼區

代碼區是 編譯時分配 主要用于存放程序運行時的代碼,代碼會被編譯成 二進制 存進內存的

驗證

口說無憑
來看看變量在內存中是如何分配的

- (void)test{NSInteger i = 123;NSLog(@"i的內存地址:%p", &i);NSString *string = @"CJL";NSLog(@"string的內存地址:%p", string);NSLog(@"&string的內存地址:%p", &string);NSObject *obj = [[NSObject alloc] init];NSLog(@"obj的內存地址:%p", obj);NSLog(@"&obj的內存地址:%p", &obj);  
}

請添加圖片描述
回顧一下
0x1是內存區開頭 用于存放
0x6是堆區開頭 主要用于存放OC對象
0x7是棧區開頭 主要存放局部變量

i 和 &string 和 &obj都屬于局部變量 存在棧區
string內的@"CJL"是字符串 存常量區
對象obj存堆區
很完美

然后這個也是對的
在這里插入圖片描述

內存使用注意事項

內存使用注意事項涵蓋了多個方面,包括避免內存泄漏、防止野指針引用、正確處理數組邊界、適當地分配和釋放內存等

  1. 內存泄露
  2. 重復釋放
  3. 野指針
  4. 數組越界
  5. 未初始化內存
  6. 緩沖區溢出

大小端模式

在這里插入圖片描述

在地址讀取時,分為大端模式與小端模式
大端模式從左向右每兩位為一組讀取
小端模式從右向左每兩位為一組讀取

iOS與macOS 均是小端模式

總結

一個程序在內存上由BSS段、data段、text段三個組成的。在沒有調入內存前,可執行程序分為代碼段、數據區和未初始化數據區三部分

BSS段:(Block Started by Symbol)
通常是指用來存放程序中未初始化的全局變量的一塊內存區域,屬于靜態內存分配。BSS段的內容并不存放在磁盤上的程序文件中。原因是內核在程序開始運行前將它們設置為0,需要存放在程序文件中的只有正文段和初始化數據段。text段和data段在編譯時已經分配了空間,而BSS段并不占用可執行文件的大小,它是由鏈接器來獲取內存的。

數據段:(data segment)
通常是指用來存放程序中已初始化的全局變量的一塊內存區域,屬于靜態內存分配。總結為:初始化的全局變量和靜態變量在已初始化區域,未初始化的全局變量和靜態變量在BSS區。

代碼段:(code segment/text segment)
通常是指用來存放程序執行代碼的一塊內存區域。該區域的大小在程序運行前就已經確定,并且內存區域通常屬于只讀, 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。

堆(heap):
用于動態分配內存,位于BSS和棧中間的地址區域,由程序員申請分配和釋放。堆是從低地址位向高地址位增長,采用鏈式存儲結構。頻繁的malloc/free造成內存空間的不連續,會產生碎片。當申請堆空間時庫函數是按照一定的算法搜索可用的足夠大的空間,因此堆的效率比棧要低的多。注:與數據結構中的堆不是一個概念,但堆的分配方式類似于鏈表。

棧(stack):
由編譯器自動釋放,存放函數的參數值、局部變量等。每當一個函數被調用時,該函數的返回類型和一些調用的信息被存放到棧中,這個被調用的函數再為它的自動變量和臨時變量在棧上分配空間。每調用一個函數一個新的棧就會被使用。棧區是從高地址位向低地址位增長的,是一塊連續的內存區域,最大容量是由系統預先定義好的,申請的棧空間超過這個界限時會提示溢出。

堆和棧的區別在于

1)管理方式:棧由編譯器自動管理,無需人為控制。而堆釋放工作由程序員控制,容易產生內存泄漏(memory leak)。
2)空間大小:在32位系統下,堆內存可以達到4G的空間(虛擬內存的大小,有面試官問過),從這個角度來看堆內存大小可以很大。但對于棧來說,一般都是有一定的空間大小的
3)碎片問題:堆頻繁new/delete會造成內存空間的不連續,造成大量的碎片,使程序效率降低(重點是如何解決?如內存池、伙伴系統等)。對棧來說不會存在這個問題,因為棧是先進后出,不可能有一個內存塊從棧中間彈出。在該塊彈出之前,在它上面的(后進的棧內容)已經被彈出。
4)生長方向:堆生長(擴展)方向是向上的,也就是向著內存地址增加的方向;棧生長(擴展)方向是向下的,是向著內存地址減小的方向增長, 可以看第一張圖。
5)分配方式:堆都是動態分配的,沒有靜態分配的堆。而棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,如局部變量分配。動態分配由alloca函數進行分配,但是棧的動態分配和堆是不同的,它的動態分配是由編譯器進行釋放,無需我們手工實現。
6)效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持(有專門的寄存器存放棧的地址,壓棧出棧都有專門的機器指令執行),這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很復雜的(可以了解侯捷老師的內存管理的視頻,關于malloc/realloc/free函數等)。例如分配一塊內存,堆會按照一定的算法,在堆內存中搜索可用的足夠大小的空間,如果沒有(可能是由于內存碎片太多),就有可能調用系統功能去增加程序數據段的內存空間,這樣就有機會分到足夠大小的內存,然后進行返回。總之,堆的效率比棧要低得多。

函數棧

函數棧又稱為棧區
與堆區相對在內存中從高地址往低地址分配

棧幀是指函數(運行中且未完成)占用的一塊獨立的連續內存區域

應用中新創建的每個線程都有專用的棧空間,棧可以在線程期間自由使用。而線程中有千千萬萬的函數調用,這些函數共享進程的這個棧空間。每個函數所使用的棧空間是一個棧幀,所有的棧幀就組成了這個線程完整的棧

函數調用是發生在棧上的

  • 每個函數的相關信息(例如局部變量、調用記錄等)都存儲在一個棧幀中
  • 每執行一次函數調用就會生成一個與其相關的棧幀
  • 然后將其棧幀壓入函數棧
  • 當函數執行結束則將此函數對應的棧幀出棧并釋放掉

上經典
在這里插入圖片描述
ARM壓棧的順序依次為當前函數指針PC、返回指針LR、棧指針SP、棧基址FP、傳入參數個數及指針、本地變量和臨時變量。如果函數準備調用另一個函數,跳轉之前臨時變量區先要保存另一個函數的參數。

其中
main stack frame為調用函數的棧幀
func1 stack frame為當前函數(被調用者)的棧幀
棧底在高地址,棧向下增長
FP就是棧基址,它指向函數的棧幀起始地址
SP則是函數的棧指針,它指向棧頂的位置

ARM也可以用棧基址和棧指針明確標示棧幀的位置,棧指針SP一直移動,ARM的特點是,兩個棧空間內的地址(SP+FP)前面,必然有兩個代碼地址(PC+LR)明確標示著調用函數位置內的某個地址

ok其實還是有不好理解的地方的
R9為什么是the 5th parameter for func1:2 func1

當函數準備調用另一個函數時,在跳轉之前,需要先保存另一個函數的參數。如果參數能夠通過寄存器(如 R0-R3)傳遞,就直接使用寄存器;如果參數超過 4 個,多出來的參數則使用棧來傳遞,并將它們放置在當前函數棧幀的臨時變量區。

所以在main函數棧幀的R9存放的是func1的第五個參數就沒問題啦

注:ARM是滿降棧

滿棧:當堆棧指針總是指向最后壓入堆棧的數據
空棧:當堆棧指針總是指向下一個將要放入數據的空位置

升棧:隨著數據的入棧,SP指針從低地址->高地址移動
降棧:隨著數據的入棧,SP指針從高地址->低地址移動

堆棧溢出

一般情況下應用程序是不需要考慮堆和棧的大小的,但是事實上堆和棧都不是無上限的,過多的遞歸會導致棧溢出,過多的alloc變量會導致堆溢出。
所以預防堆棧溢出的方法:
(1)避免層次過深的遞歸調用
(2)不要使用過多的局部變量,控制局部變量的大小
(3)避免分配占用空間太大的對象,并及時釋放
(4)適當的情景下調用系統API修改線程的堆棧大小

棧的作用

(1)保存局部變量
(2)參數傳遞
(3)保存寄存器的值

參考博客

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

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

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

相關文章

51單片機STC89C52RC——19.1 SG90舵機(伺服電機)

目的/效果 獨立按鍵K1,K2 實現加舵機減角度增減,LCD1602顯示舵機轉角度數(上電默認90度) 一,STC單片機模塊 二,SG90舵機 2.1 簡介 舵機只是我們通俗的叫法,它的本質是一個伺服電機&#xf…

react 案例的實現

先看一下如下效果 效果 這是一個 簡單的 效果 左邊是用戶名進行登錄 右邊是一個答題還有遮罩 相信大家還有剛剛創建好的 react 腳手架了,沒有的話可以運行以下命令 creact-react-app 項目名稱 把項目名稱四個字 改成 自己想要的一個名字 最好是英文的在 App.js中去…

python xpath常用代碼功能

1、從文件中讀取html內容,然后xpath加載 with open(FilePath, r,encodingutf8) as file:html file.read() tree etree.HTML(html) 2、基本定位語法 / 從根節點開始選取 /html/div/span // 從任意節點開始選取 //input . 選取當前節點 .…

Web開發:<br>標簽的作用

br作用 介紹基本用法常見用途注意事項使用CSS替代 介紹 在Web開發中&#xff0c;<br> 標簽是一個用于插入換行符的HTML標簽。它是“break”的縮寫&#xff0c;常用于需要在文本中強制換行的地方。<br> 標簽是一個空標簽&#xff0c;這意味著它沒有結束標簽。 基本…

Python小工具—txt轉excel和word

1.txt轉excel import openpyxl# 創建一個新的Excel工作簿 wb = openpyxl.Workbook() sheet = wb.active# 題干和答案的標題 sheet[A1] = 題干 sheet[B1] = 答案# 打開txt文件并讀取內容 with open(xiti.txt, r, encoding=utf-8) as file:lines = file.readlines()# 初始變量 c…

VisualTreeHelper.GetChildrenCount

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;VisualTreeHelper.GetChildrenCount 是一個非常有用的方法&#xff0c;用于獲取指定視覺對象的子元素數量。這對于遍歷復雜的用戶界面樹結構以進行查找、操作或檢查特定元素是非常有幫助的。 Visu…

【java深入學習第7章】用 Spring Boot 和 Java Mail 輕松實現郵件發送功能

引言 在現代的企業應用中&#xff0c;郵件發送是一個非常常見的功能。無論是用戶注冊后的驗證郵件&#xff0c;還是系統通知郵件&#xff0c;郵件服務都扮演著重要的角色。本文將介紹如何在Spring Boot項目中整合Java Mail&#xff0c;實現發送郵件的功能。 一、準備工作 在…

【Ubuntu】安裝使用pyenv - Python版本管理

當我們在Ubuntu上使用Python進行開發的時候&#xff0c;可能會遇到版本不兼容的問題&#xff0c;當然你可以選擇使用apt的方式安裝不同版本的python環境 但是存在一定的問題&#xff1a;安裝不同版本的Python通常不會改變默認的python3命令指向的版本&#xff0c;而且就算你進行…

分布式對象存儲minio

本教程minio 版本&#xff1a;RELEASE.2021-07-*及以上 1. 分布式文件系統應用場景 互聯網海量非結構化數據的存儲需求 電商網站&#xff1a;海量商品圖片視頻網站&#xff1a;海量視頻文件網盤 : 海量文件社交網站&#xff1a;海量圖片 1.1 Minio介紹 MinIO 是一個基于Ap…

ubuntu服務器部署vue springboot前后端分離項目

上傳構建好的vue前端文件 vscode構建vue項目&#xff0c;會生成dist目錄 npm run build在服務器root目錄新建/projects/www目錄&#xff0c;把dist目錄下的所有文件&#xff0c;上傳到此目錄中 上傳ssl證書 上傳ssl證書到/projects目錄中 配置nginx 編輯 /etc/nginx/site…

微服務邊界守衛:Eureka中服務隔離策略的實現

微服務邊界守衛&#xff1a;Eureka中服務隔離策略的實現 在微服務架構中&#xff0c;服務隔離是一項關鍵策略&#xff0c;用于確保服務之間的故障不會相互影響&#xff0c;同時提供更加安全和穩定的運行環境。Eureka作為Netflix開源的服務發現框架&#xff0c;提供了一些機制來…

Java 網絡協議面試題答案整理,最新面試題

TCP和UDP的主要區別是什么? TCP(傳輸控制協議)和UDP(用戶數據報協議)的主要區別在于TCP是面向連接的協議,而UDP是無連接的協議。這導致了它們在數據傳輸方式、可靠性、速度和使用場景方面的不同。 1、連接方式: TCP是面向連接的協議,數據傳輸前需要三次握手建立連接。U…

區塊鏈與云計算的融合:新時代數據安全的挑戰與機遇

隨著信息技術的迅猛發展&#xff0c;云計算和區塊鏈技術作為兩大前沿技術在各自領域內展示出了巨大的潛力。而它們的結合&#xff0c;即區塊鏈與云計算的融合&#xff0c;正在成為數據安全領域的新趨勢。本文將探討這一融合對數據安全帶來的挑戰和機遇&#xff0c;以及其在企業…

平替ChatGPT的多模態智能體來了

在人工智能領域&#xff0c;多模態技術的融合與應用已成為推動技術革新的關鍵。今天&#xff0c;我們用智匠AI實現了完全由國產模型驅動的多模態智能體——智醬v0.1.0&#xff0c;它不僅能夠媲美ChatGPT的多模態能力&#xff0c;更在聯網搜索、圖片識別、畫圖及圖表生成等方面展…

redis原理之底層數據結構(二)-壓縮列表

1.緒論 壓縮列表是redis最底層的結構之一&#xff0c;比如redis中的hash&#xff0c;list在某些場景下使用的都是壓縮列表。接下來就讓我們看看壓縮列表結構究竟是怎樣的。 2.ziplist 2.1 ziplist的組成 在低版本中壓縮列表是由ziplist實現的&#xff0c;我們來看看他的結構…

Stable Diffusion AI繪畫全攻略:從理論到實戰,解鎖創意圖畫的魔法之門

在科技的飛速發展中&#xff0c;Stable Diffusion AI繪畫技術為藝術創作帶來了前所未有的革命性變化。這項技術由CompVis、Stability AI和LAION聯合研發&#xff0c;通過深度學習模型&#xff0c;將文字描述轉化為生動的藝術作品&#xff0c;極大地拓寬了創意與想象的邊界。本文…

大數據面試SQL題-筆記01【運算符、條件查詢、語法順序、表連接】

大數據面試SQL題復習思路一網打盡&#xff01;(文檔見評論區)_嗶哩嗶哩_bilibiliHive SQL 大廠必考常用窗口函數及相關面試題 大數據面試SQL題-筆記01【運算符、條件查詢、語法順序、表連接】大數據面試SQL題-筆記02【...】 目錄 01、力扣網-sql題 1、高頻SQL50題&#xff08…

TCP、UDP、TCP與UDP的區別及聯系

目錄 TCP和UDP區別1.連接2.交互個數3.可靠性4.傳輸方式5.適用場景 怎么實現一個可靠的UDP傳輸TCP詳解UDP詳解 TCP和UDP區別 1.連接 TCP 面向連接的&#xff0c;傳輸數據前先要建立連接。 UDP 是不需要連接&#xff0c;即刻傳輸數據。 2.交互個數 TCP 是一對一通信。 UDP 支…

數據結構——hash(hashmap源碼探究)

hash是什么&#xff1f; hash也稱為散列&#xff0c;就是把任意長度的輸入&#xff0c;通過散列算法&#xff0c;變成固定長度的輸出&#xff0c;這個輸出值就是散列值。 舉例來說明一下什么是hash&#xff1a; 假設我們要把1~12存入到一個大小是5的hash表中&#xff0c;我們…

礦產資源潛力預測不確定性評價

研究目的&#xff1a; 不確定性評估&#xff1a; 到底什么叫不確定性&#xff0c;簡單來說就是某區域內的礦產資源量&#xff0c;并不確定到底有多少&#xff0c;你需要給出一個評估或者分布。 研究方法&#xff1a; 1.以模糊集來表示某些量&#xff1a; 關于什么是模糊集&am…