Objective-C 的記憶體管理基於引用計數。本文用純 C 實現一個迷你引用計數系統:xalloc(分配+計數=1)、xretain(計數+1)、xrelease(計數-1,歸零釋放)、xretainCount(查看計數),揭示 ARC 底層原理。
分配塊結構:
[ refcount (4 bytes) ][ user data (n bytes) ]
^ real_ptr ^ user_ptr (返回給用戶)
n + 4 字節,前 4 字節存引用計數(int)。real_ptr + 1 作為用戶指針,用戶無感知頭部元數據。#include <stdio.h>
#include <stdlib.h>
void *xalloc(size_t size) {
int *real = malloc(size + sizeof(int));
if (!real) return NULL;
real[0] = 1; // 計數初始化 1
return real + 1; // 返回用戶數據區指針
}
void *xretain(void *ptr) {
if (!ptr) return NULL;
int *real = (int*)ptr - 1;
real[0]++;
return ptr;
}
void xrelease(void *ptr) {
if (!ptr) return;
int *real = (int*)ptr - 1;
if (real[0] == 1) {
printf("Memory [%p] truly freed.\n", ptr);
free(real);
} else {
real[0]--;
}
}
int xretainCount(void *ptr) {
if (!ptr) return 0;
return *((int*)ptr - 1);
}
int main() {
int *p = xalloc(sizeof(int)); // 計數=1
printf("p count: %d\n", xretainCount(p));
int *q = xretain(p); // 計數=2
printf("p count: %d\n", xretainCount(p));
xrelease(p); // 計數=1
printf("q count: %d\n", xretainCount(q));
xrelease(q); // 計數=0,真正釋放
return 0;
}
p count: 1
p count: 2
q count: 1
Memory [0x...] truly freed.
| C 模擬 | Objective-C |
|---|---|
| xalloc | alloc / new |
| xretain | retain |
| xrelease | release |
| xretainCount | retainCount |
| 頭部 int 計數 | isa 指針偏移後的引用計數表(側表 Side Table) |
isa 指針佔用),而是存全局側表(SideTable),以 object address 為鍵。retain/release/autorelease,而非運行時自動。weak 參考需側表支援,釋放時自動置 nil。此模擬揭示引用計數核心:元數據與用戶數據分離、計數歸零觸發釋放。理解此模型,有助於排查 OC 記憶體洩漏、過釋、循環引用等疑難雜症。