- 系統(tǒng)實(shí)際分配了
16 字節(jié)給 NSOject對(duì)象, 通過(guò) malloc_size 函數(shù)獲得, 查看源碼
)可以知道平臺(tái)底層對(duì)分配內(nèi)存空間做了對(duì)齊操作, 在 libmalloc 中的宏定義 NANO_MAX_SIZE = 256 是說(shuō) nano 這種分配空間方式里面最大分配 256 個(gè)字節(jié), 備注里面有說(shuō)是 16 的倍數(shù)
- 但
NSOject 對(duì)象內(nèi)部使用了 8 個(gè)字節(jié), 通過(guò) class_getInstanceSize 函數(shù)獲得, 也就是說(shuō)該函數(shù)獲取的是最少需要的字節(jié)數(shù), 是結(jié)構(gòu)體對(duì)齊后的字節(jié)數(shù), 與 sizeof 計(jì)算出來(lái)的數(shù)值一樣
https://opensource.apple.com/tarballs
- 轉(zhuǎn) iOS --> 64bits (arm64), 可以查看翻譯成 C 的代碼 中類(lèi)的結(jié)構(gòu)體
$ xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
# 轉(zhuǎn)換 LLVM 命令
$ clang -emit-llvm -S main.m
#import <objc/runtime.h>
#import <malloc/malloc.h>
- 下面是我的測(cè)試代碼, 放入
main.m 就可以
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>
@interface Student : NSObject
{
@public
int _no;
int _age;
}
@end
@implementation Student
@end
/**
* 一個(gè) NSOject 對(duì)象所占內(nèi)存大小 ? (64bits)
* 系統(tǒng)分配了 16 字節(jié)給 NSOject 對(duì)象, 通過(guò) malloc_size 函數(shù)獲得
* 但 NSOject 對(duì)象內(nèi)部使用了 8 個(gè)字節(jié), 通過(guò) class_getInstanceSize 函數(shù)獲得
*/
void objc_instance_size (void);
void student_instance_size (void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
objc_instance_size();
student_instance_size();
}
return 0;
}
/**
* NSOject_Implementation
* clang 編譯后的 NSObject 實(shí)質(zhì)為一個(gè) C 的結(jié)構(gòu)體如下
* 數(shù)據(jù)結(jié)構(gòu)
*/
struct NSObject_IMPL {
Class isa;
// typedef struct objc_class *Class;
// Class 指向結(jié)構(gòu)體的指針
// 指針在 64bits 上是 8 個(gè)字節(jié)
};
// NSObject.h
//@interface NSObject <NSObject> {
// Class isa OBJC_ISA_AVAILABILITY;
//}
void objc_instance_size () {
NSObject *objc = NSObject.alloc.init;
size_t objc_sizes = class_getInstanceSize(objc.class);
// 獲取 NSOject 類(lèi)的實(shí)例對(duì)象中成員變量?jī)?nèi)存對(duì)齊后所占內(nèi)存的大小(最少需要的空間, 值和 sizeof 計(jì)算的一樣)
NSLog(@"objc_sizes => %zd", objc_sizes);
/* class_getInstanceSize 源碼中調(diào)用了下面的函數(shù), 所以是對(duì)齊過(guò)的 ivar size
// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() {
return word_align(unalignedInstanceSize());
}
*/
size_t malloc_sizes = malloc_size((__bridge const void *)(objc));
// 獲取 objc 指針指向所占內(nèi)存的大小(實(shí)際開(kāi)辟的, 通過(guò)源碼可以看到 iOS 是 16 的倍數(shù)對(duì)齊 libmalloc 中的宏定義 NANO_MAX_SIZE)
NSLog(@"malloc_sizes => %zd", malloc_sizes);
/* 在 _class_createInstanceFromZone 也就是 allocWithZone 的底層實(shí)現(xiàn)中調(diào)用了以下函數(shù)來(lái)計(jì)算實(shí)例大小
size_t instanceSize(size_t extraBytes) {
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}
*/
// OC 轉(zhuǎn)成 CPP, 不同的平臺(tái)轉(zhuǎn)換出來(lái)的代碼是不一樣的
// 轉(zhuǎn) iOS -> 64bits (arm64)
// xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
// 源碼: https://opensource.apple.com/tarballs
}
void student_instance_size () {
/* clang 編譯后的 Student 實(shí)質(zhì)為一個(gè) C 的結(jié)構(gòu)體如下 */
struct Student_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _no;
int _age;
};
Student *std = Student.alloc.init;
std->_no = 2;
std->_age = 10;
size_t malloc_sizes = malloc_size((__bridge const void *)(std));
// 獲取 std 指針指向所占內(nèi)存的大小
NSLog(@"std_malloc_sizes => %zd", malloc_sizes);
struct Student_IMPL *std_imp = (__bridge struct Student_IMPL *)(std);
NSLog(@"std_imp->_no: %d \t std_imp->_age: %d", std_imp->_no, std_imp->_age);
}
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。