【iOS】alloc的實際流程

目錄

前言

為什么不按源碼流程調用?

alloc的調用流程


前言

在之前的博客中我們有學習到過alloc的底層原理,沿著源碼一步步找到了alloc的調用鏈——alloc—>_objc_rootAlloc—>callAlloc—>_objc_rootAllocWithZone—>_class_createInstanceFromZone,但其實在實際的alloc過程中,并不是這個調用流程,如果對NSObject的alloc加上斷點調試就會發現,alloc流程并沒有進入源碼,接下來我們來探究一下為什么會這樣以及真實的調用流程。

為什么不按源碼流程調用?

在實際運行中,[NSObject alloc][MyClass alloc] 這類調用通常不會真正進入 libobjc 的源碼層(比如 _objc_rootAlloc,而是走了更加高效的底層路徑,這是由于 Apple 對運行時做了大量優化(比如匯編級別快速路徑、ISA-optimized fast path)來避免頻繁進入 C 層函數。

1.對于非NSObject類, objc_msgSend是匯編函數,非普通 C 函數

  • 它大多數時候在匯編層 直接查找 IMP 并跳轉執行,不會進入 Objective-C runtime 的 C 函數實現。

  • 也就是說,objc_msgSend(obj, @selector(alloc)) 通常直接跳到了元類中的 +alloc 的 IMP。(這里涉及到后面cache_t的方法緩存,如果命中了Cache,就不會走完整的流程)

  1. 對于NSObject, 是基礎類,系統做了特殊優化

  • 對于 NSObject和一些常見類,Apple 使用了 匯編級別的 fast path,這意味著即便你打斷點試圖進入 _objc_rootAlloc,你可能根本進不去。

  • 常見的“未命中源碼”的情況說明使用的是緩存或特殊入口。

alloc的調用流程

通過調用alloc后的堆棧詳情我們就可以發現,無論是NSObject類還是自定義類,調用alloc方法最開始走的都是objc_alloc而不是objc_rootAlloc。這是因為消息轉發時系統在底層幫我們轉發到了objc_alloc。我們來看看objc_alloc的源碼實現

可以發現其實他和objc_rootAlloc的實現是一樣的,調用callAlloc。

回顧之前callAlloc的實現

可以看到callAlloc中分為幾個分支來處理

對于NSObjcet類,初始化在llvm編譯時就已經初始化好了,因此緩存中已經有alloc/allocWithZone方法了,hasCustomAWZ()為false,那么!cls->ISA()->hasCustomAWZ()就為true。

因此NSObjcet在此時會進入_objc_rootAllocWithZone并調用_class_createInstanceFromZone,后面的步驟就和之前說的一樣了,這就是為什么NSObjct沒有走alloc方法

而對于自定義類,初次創建時沒有默認的alloc/allocWithZone實現,所以繼續向下執行進入到消息發送流程,消息轉發時會向父類找,最終找到NSObjcet的alloc并調用,即[NSObjcet alloc],這時會來到_objc_rootAlloc,進入后再次調用callAlloc,這次調用的是NSObject類的,緩存中存在alloc/allocWithZone實現,就接著走_objc_rootAllocWithZone方法,后面步驟也就和之前一樣了。所以自定義類在調用alloc時會走兩次callAlloc

總結一下,NSObjcet的調用鏈如下圖:

自定義類的調用鏈如下圖:

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

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

相關文章

MySQL 故障排查與生產環境優化

目錄 一、前置知識點 MySQL的運行原理 1. 客戶端連接 2. SQL 解析與優化 3. 存儲引擎處理 4. 日志與持久化 二、MySQL 單實例故障排查 (1)故障現象1 (2)故障現象2 (3)故障現象3 (4&am…

C++學習:六個月從基礎到就業——C++20:模塊(Modules)與其他特性

C學習:六個月從基礎到就業——C20:模塊(Modules)與其他特性 本文是我C學習之旅系列的第五十三篇技術文章,也是第三階段"現代C特性"的第十五篇,深入探討C20引入的模塊(Modules)系統及其他重要特性。查看完整系列目錄了解…

Vue百日學習計劃Day36-42天詳細計劃-Gemini版

總目標: 在 Day 36-42 理解組件化開發的思想,熟練掌握 Vue 組件的注冊、Props、Events、v-model、Slots、Provide/Inject 等核心概念和實踐,能夠構建可復用和易于維護的組件結構。 所需資源: Vue 3 官方文檔 (組件基礎): https://cn.vuejs.org/guide/es…

深入解析Spring Boot與Kafka集成:構建高效消息驅動微服務

深入解析Spring Boot與Kafka集成:構建高效消息驅動微服務 引言 在現代微服務架構中,消息隊列扮演著至關重要的角色,而Apache Kafka憑借其高吞吐量、低延遲和可擴展性,成為了許多企業的首選。本文將詳細介紹如何在Spring Boot應用…

谷歌 NotebookLM 即將推出 Sparks 視頻概覽:Gemini 與 Deep Research 加持,可生成 1 - 3 分鐘 AI 視頻

近期,谷歌旗下的 NotebookLM 即將推出一項令人矚目的新功能 ——Sparks 視頻概覽。這一功能借助 Gemini 與 Deep Research 的強大能力,能夠生成 1 - 3 分鐘的 AI 視頻,為用戶帶來全新的內容創作與信息獲取體驗。 NotebookLM:AI 筆…

第十六屆藍橋杯復盤

文章目錄 1.數位倍數2.IPv63.變換數組4.最大數字5.小說6.01串7.甘蔗8.原料采購 省賽過去一段時間了,現在復盤下,省賽報完名后一直沒準備所以沒打算參賽,直到比賽前兩天才決定參加,賽前兩天匆匆忙忙下載安裝了比賽要用的編譯器ecli…

Manus AI 突破多語言手寫識別技術壁壘:創新架構、算法與應用解析

在人工智能領域,手寫識別技術作為連接人類自然書寫與數字世界的橋梁,一直備受關注。然而,多語言手寫識別面臨諸多技術挑戰,如語言多樣性、書寫風格差異、數據稀缺性等。Manus AI 作為該領域的領軍者,通過一系列創新技術…

25考研經驗貼(11408)

聲明:以下內容都僅代表個人觀點 數學一(130) 25考研數學一難度介紹:今年數學一整體不難,尤其是選填部分,大題的二型線面和概率論大題個人感覺比較奇怪,其他大題還是比較容易的。.26如何準備&a…

嵌入式軟件--stm32 DAY 6 USART串口通訊(下)

1.寄存器輪詢_收發字符串 通過寄存器輪詢方式實現了收發單個字節之后,我們趁熱打鐵,爭上游,進階到字符串。字符串就是多個字符。很明顯可以循環收發單個字節實現。 然后就是接收字符串。如果接受單個字符的函數放在while里,它也可…

QT使用QXlsx讀取excel表格中的圖片

前言 讀取excel表格中的圖片的需求比較小眾,QXlsx可以操作excel文檔,進行圖片讀取、插入操作,本文主要分享單獨提取圖片和遍歷表格提取文字和圖片。 源碼下載 github 開發環境準備 把下載的代碼中的QXlsx目錄,整個拷貝到所創建…

抽獎相關功能測試思路

1. 抽獎系統功能測試用例設計(登錄 每日3次 中獎40% 道具兌換碼) ? 功能點分析 必須登錄后才能抽獎每天最多抽獎3次抽獎有 40% 概率中獎中獎返回兌換碼 ? 測試用例設計 編號 用例描述 前置條件 操作 預期結果 TC01 未登錄時抽獎 未登錄 …

Unity editor文件數UI(支持勾選框)

unity editor文件數(支持勾選框) 使用的時候new一個box即可 using Sirenix.OdinInspector; using Sirenix.OdinInspector.Editor; using System; using System.Collections; using System.Collections.Generic; using UnityEngine;[Serializable] publ…

RabbitMQ通信模式(Simplest)Python示例

RabbitMQ通信模式-Python示例 0.RabbitMQ官網通信模式1.Simplest(簡單)模式1.1 發送端1.2 接收端 0.RabbitMQ官網通信模式 1.Simplest(簡單)模式 1.1 發送端 # -*- coding: utf-8 -*- """ Author: xxx date: 2025/5/19 11:30 Description: Simaple簡單模…

隨筆20250519 Async+ThreadPoolTaskExecutor?定義線程池進階實戰

1.ThreadPoolTaskExecutor線程池 有哪?個重要參數, 什么時候會創建線程 1.核心綫程數 查看核心綫程數目是否已經滿,未滿 創建一條綫程 執行任務,已滿負責執行第二部 2.阻塞隊列 查看阻塞隊列是否已經滿,未滿將任務加入阻塞隊列&…

YOLO11解決方案之實例分割與跟蹤探索

概述 Ultralytics提供了一系列的解決方案,利用YOLO11解決現實世界的問題,包括物體計數、模糊處理、熱力圖、安防系統、速度估計、物體追蹤等多個方面的應用。 實例分割是一項計算機視覺任務,涉及在像素級別識別和勾勒圖像中的單個對象。與只按類別對像素進行分類的語義分割…

VScode各文件轉化為PDF的方法

文章目錄 代碼.py文件.ipynb文本和代碼夾雜的文件方法 1:使用 VS Code 插件(推薦)步驟 1:安裝必要插件步驟 2:安裝 `nbconvert`步驟 3:間接導出(HTML → PDF)本文遇見了系列錯誤:解決方案:問題原因步驟 1:降級 Jinja2 至兼容版本步驟 2:確保 nbconvert 版本兼容替代…

現代計算機圖形學Games101入門筆記(十五)

蒙特卡洛積分 為什么用蒙特卡洛積分,用來做什么?跟黎曼積分區別,黎曼積分是平均分成n等分,取每個小塊中間的值取計算每個小塊面積,再將n份集合加起來。蒙特卡洛積分就是隨機取樣,假設隨機取樣點xi,對應的f…

軟件架構之-論高并發下的可用性技術

論高并發下的可用性技術 摘要正文摘要 ;2023年2月,本人所在集團公司承接了長三角地區某省漁船圖紙電子化審查系統項目開發,該項目旨在為長三角地區漁船建造設計院、以及漁船審圖機構提供一個便捷化的服務平臺。在此項目中,我作為項目組成員參與了項目建設工作,并擔任系統架…

Q-learning 算法學習

Q-learning是一種經典的無模型、基于價值的算法,它通過迭代更新狀態-動作對的Q值,最終找到最優策略。 一 Q-learning的核心思想 1.1目標 學習一個狀態-動作價值函數 ,表示在狀態 s 下執行動作 a 并遵循最優策略后的最大累積獎勵。 的核心…

鴻蒙生態崛起:開發者機遇與挑戰并存

💓 博客主頁:倔強的石頭的CSDN主頁 📝Gitee主頁:倔強的石頭的gitee主頁 ? 文章專欄:《熱點時事》 期待您的關注 目錄 引言 一、何為鴻蒙生態? 二、在鴻蒙生態下開發時遇到的挑戰 三、對于鴻蒙生態未…