[toc]
## 前言
根據內存區塊的引用狀態劃分內存:
- `緩存內存(Cached memory)`
- `泄漏內存(Leaked memory)`
- `廢棄內存(Abandoned memory)`
- `僵尸內存(Zombies memory)`
`緩存內存`:正常使用的內存
`泄漏內存`:`沒有引用也沒有被釋放的內存`。可以用`leaks`檢測到,MRC常見,ARC多為Core相關庫未release導致
`廢棄內存`:`內存仍存在引用,但是無法被使用到`。無法用leaks檢測到,可嘗試使用`Allocations`排查,一般為`循環引用導致`
## 一、內存分類
根據`內存區塊`的引用狀態,可以把內存分為緩存內存(Cached memory)、泄漏內存(Leaked memory)、廢棄內存(Abandoned memory)和僵尸內存(Zombies memory),其中`泄漏內存`和`廢棄內存`為`內存增長`的主要原因,`僵尸內存`的使用會導致程序的`crash`
>Cached memory: Memory still referenced by your application that might be used again for better performance.
>
>Leaked memory: Memory unreferenced by your application that cannot be used again or freed (also detectable by using the Leaks instrument).
>
>Abandoned memory: Memory still referenced by your application that has no useful purpose.
Zombies: objects that are called after they’ve been released and no longer exist
`1.泄漏內存`:內存沒有被釋放,也沒有對應的引用,可以被Leaks工具檢測到。
常見情形:MRC中Retain沒有對應的Release,ARC中一般出現這種情況多為`c相關對象`未調用相對應的`release`方法
```objectivec
示例1:
NSString * testStr = (__bridge NSString *)(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,(CFStringRef)[NSString stringWithFormat:@"%@",self],NULL,CFSTR("!*'();:@&=+$,/?%#[]"),kCFStringEncodingUTF8));
// CFRelease(testStr);
示例2:
CGImageRef imageRef = CGImageCreateWithImageInRect([[UIImage imageNamed:@"xxx"] CGImage], CGRectZero);
// CFRelease(imageRef);
```
`2.廢棄內存`:`內存沒有有效的引用,無法被程序使用`,無法用Leaks檢測到,可以通過Allocations分析出
常見情形:主要為循環引用和常駐對象強持有,如delegate聲明為強引用,屬性block強持有外部變量導致的循環引用,NSTimer未及時釋放等
```objectivec
實例1:
self.callback = ^ {
NSLog("%@",self);
}
實例2:
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(task) userInfo:nil repeats:YES];
// [self.timer invalidate];
// 需要注意的是如果對象由于Timer被runloop強引用時,在該對象的dealloc中是停止定時器是不生效的,因為由于強引用導致該對象不會被釋放,dealloc便不會被調用
```
`3.僵尸內存`:`對象內存已經被釋放,仍存在對應的引用指向該部分區域`。通過引用使用該部分區域可能會造成`EXC_BAD_ACCESS`異常
常見情形:已經釋放的對象執行release或收到其他的調用;對象創建后沒有被強引用卻被使用
## 二、內存泄漏排查
**1.1 靜態分析**
通過`Xcode Analyze`功能靜態分析代碼,選中Xcode工程菜單 `Product - Analyze`,靜態分析可以分析出程序無用變量,無法執行到的分支,廢棄接口,靜態內存泄漏等
>注:cocoapods debug切換到release需要使用pod install,否則有可能無法生成release.xcconfig

**1.2 Runtime分析 Leaks&Allocations**
通過Xcode `Leak`工具運行時分析代碼 Xcode選中`Product - Profile`,以Profile方式安裝程序到真機,打開Instruments中的Leaks,選中左上角的錄制按鈕,選中對應程序開始執行分析
**常用設置:**
`Call Tree`:調用棧方式查看泄漏來源
`Invert Call Tree`:反轉調用堆棧,可以直接把泄漏的調用處顯示在最頂層
`Hide System Libraries`:隱藏系統庫相關符號,由于沒有符號化信息,建議隱藏
`Automatic Snapshotting`:自動掃描,掃描一次耗時較大,大客戶端建議關閉自動掃描或者增加掃描間隔,或使用手動進行snapshot,否則可能會卡頓和程序異常退出
`Snapshot Now`:立馬掃描生成一次內存快照

-------------

----------
)
>注:如果無法顯示符號化后的堆棧信息,需要查看工程配置中是否在Release下生成對應的dsym

- 前言
- WebRTC知識集
- iOS 集成WebRTC各知識點小集
- iOS WebRTC集成時遇到的問題總結
- WebRTC多人音視頻聊天架構及實戰
- iOS端 使用WebRTC實現1對1音視頻實時通話
- iOS 基于WebRTC的點對點音視頻通信 總結篇
- WebRTC Native 源碼導讀 - iOS 相機采集實現分析
- OC 底層原理
- OC runtime 運行時詳解
- GCD dispatch_queue_create 創建隊列
- iOS底層 Runtime深入理解
- iOS底層 RunLoop深入理解
- iOS底層 Block的本質與使用
- iOS內存泄漏
- iOS中isKindOfClass和isMemberOfClass
- 從預編譯的角度理解Swift與Objective-C及混編機制
- 移動支付集成
- iOS 微信支付集成及二次封裝
- iOS 支付寶支付 Alipay集成及二次封裝
- iOS Paypal 貝寶支付集成及二次封裝
- iOS 微信、支付寶、銀聯、Paypal 支付組件封裝
- iOS 微信、支付寶、銀聯支付組件的進一步設計
- iOS 組件化
- iOS 組件化實施過程
- iOS 組件化的二進制化
- 使用pod package打包framework 實現組件的二進制化
- iOS 自制Framework 獲取指定bundle并讀取里面的資源
- .podSpec文件相關知識整理
- 開發并上傳靜態庫到CocoaPods
- pod引用第三方庫的幾種方式
- 如何在.podspec 文件中添加對本地庫的依賴
- lipo 命令合并真機與模擬器生成的framework
- iOS多線程
- NSOperation相關知識點
- 自定義NSOperation
- ios多個網絡請求之間的并行與串行場景的處理
- iOS動畫
- ios animation 動畫學習總結
- CABasicAnimation使用總結
- UITableView cell呈現的動效整理
- CoreAnimation動畫使用詳解
- iOS音視頻開發
- iOS 音視頻開發之AVCaptureMetadataOutput
- iOS操作本地視頻 - 獲取,壓縮,取第一幀
- 使用 GPUImage 實現一個簡單相機
- 直播App架構及思維導圖
- 如何快速的開發一個完整的iOS直播app
- iOS視頻拖動預覽及裁剪
- iOS 直播流程概述
- iOS直播:評論框與粒子系統點贊動畫
- iOS音視頻開發 - 采集
- 基于AVFoundation實現視頻錄制的兩種方式
- Swift知識集
- Swift 的枚舉、結構體和類詳解
- Swift 泛型詳解
- Swift屬性的包裝器@PropertyWrapper
- SwiftHub項目 之網絡層封裝的一點見解
- Moya+RxSwift+HandyJson 實現網絡請求及模型轉換
- Swift開發小記(含面試題)
- RxSwift 入坑手冊 - 基礎概念
- 理解 Swift 中的元類型:.Type 與 .self
- Swift HandyJSON庫中的類型相互轉換的實現
- Swift 中使用嵌套結構體定義一組相關的常量
- Swift Type-Erased(類型擦除)
- Swift中的weak和unowned關鍵字
- Swift 中的錯誤處理
- Swift中的Result 類型的簡單介紹
- Swift Combine 入門導讀
- Swift CustomStringConvertible 協議的使用
- 跨平臺
- Cordova跨平臺方案 iOS工程創建的步驟
- 使用Cordova 打包WebApp為原生應用詳解 (加殼封裝)
- RAC響應式編程
- 快速上手ReactiveCocoa之基礎篇
- RAC ReactiveCocoa 使用小集
- 優雅的 RACCommand
- 三方庫集成及使用
- 融云IM iOS sdk 集成 一篇就夠了
- iOS YYTextView使用筆記
- iOS YYLabel使用筆記
- iOS 蘋果集成登錄及蘋果圖標的制作要求
- iOS 面向切面編程 Aspects 庫的使用
- VKMsgSend庫對oc runtime的封裝
- OC Protocol協議分發器
- iOS 高德地圖實現大頭針展示,分級大頭針,自定制大頭針,在地圖上畫線,線和點共存,路線規劃(駕車路線規劃),路線導航,等一些常見的使用場景
- 工作總結
- 自定義UINavigationBar 適配iOS11, iOS15的問題
- SFSafariViewController 加載的網頁與原生oc之間的交互
- UICollectionView 設置header的二種方法
- UIPanGestureRecognizer進行視圖滑動并處理手勢沖突
- OC與Swift混編 注意事項
- UICollectionView 設置水平滑動后,調整每個Item項的排列方式
- oc 下定義字符串枚舉
- 高性能iOS應用開發中文版讀書筆記
- iOS 圖集滑動到最后時添加“顯示更多”效果的view組件 實現
- CocoaPods 重裝
- WKWebview使用二三事
- IOS電商首頁如何布局
- iOS中的投屏方案
- CGAffineTransform 介紹
- 用Block實現鏈式編程
- iOS 本地化簡明指南
- iOS 檢查及獲取相機、麥克風、相冊、位置等權限
- iOS 手勢UIGestureRecognizer詳解
- ios 編譯時報 Could not build module xxx 的解決方法嘗試
- iOS 常見編譯報錯及解決方案匯總(持續更新)
- AVMakeRectWithAspectRatioInsideRect 的使用
- graphhopper-ios 編譯過程詳解
- 算法
- iOS實現LRU緩存
- 架構
- IOS項目架構
- 其他雜項
- 推薦一個好用的Mac精品軟件下載站
- 如何能成為一位合格的職業經理人
- 零基礎怎么學習視頻剪輯?這篇初剪輯學者指南你一定不要錯過
- 免費SSL證書的制作
- 《一部手機拍全景》匯總課
- Linux下JAVA常用命令大全
- 即時通訊
- 通訊協議與即時通訊雜談
- 簡述移動端IM開發的那些坑:架構設計、通信協議和客戶端
- 基于實踐:一套百萬消息量小規模IM系統技術要點總結
- PaddleOCR 文字識別深度學習
- PaddleOCR mac 安裝指南
- PaddleOCR 標注工具PPOCRLabel的使用
- PaddleOCR 更換模型
- PaddleOCR 自制模型訓練