You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
static__attribute__((always_inline))
id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
bool cxxConstruct = true,
size_t *outAllocatedSize = nil)
{
if (!cls) return nil;
assert(cls->isRealized());
// Read class's info bits all at once for performance//判断当前class或者superclass是否有.cxx_construct构造方法的实现bool hasCxxCtor = cls->hasCxxCtor();
//判断当前class或者superclass是否有.cxx——destruct析构方法的实现bool hasCxxDtor = cls->hasCxxDtor();
bool fast = cls->canAllocNonpointer();
//通过进行内存对齐得到实例大小size_t size = cls->instanceSize(extraBytes);
if (outAllocatedSize) *outAllocatedSize = size;
id obj;
if (!zone && fast) {
obj = (id)calloc(1, size);
if (!obj) return nil;
//初始化实例的isa指针
obj->initInstanceIsa(cls, hasCxxDtor);
}
else {
if (zone) {
obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size);
} else {
obj = (id)calloc(1, size);
}
if (!obj) return nil;
// Use raw pointer isa on the assumption that they might be // doing something weird with the zone or RR.
obj->initIsa(cls);
}
if (cxxConstruct && hasCxxCtor) {
obj = _objc_constructOrFree(obj, cls);
}
return obj;
}
什么是内存对齐?
元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每个元素放置到内存中时,它都会认为内存是按照自己的大小(通常它为4或8)来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始,这就是所谓的内存对齐。
下图是结构体在32bit和64bit环境下各基本数据类型所占的字节数:
为什么要内存对齐?
内存对齐规则
#pragma pack(n) 对齐系数
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
其中,Xcode 中默认为**#pragma pack(8)
举一些例子
这里你只需要关注class_getInstanceSize的大小,暂时不用管malloc_size,与sizeof的值。
根据上面的例子,添加2个char属性。
调整属性的位置
看一下结构体的情况
再来一个嵌套结构体
分析
libmalloc
的源码由上面的结果知道,为什么对象生成的内存和系统开辟的内存是不一样的呢?
为了搞清楚还是需要用到上一篇文章OC底层-对象的alloc流程探究(1)里面源码的
_class_createInstanceFromZone
方法过滤多余的代码后,得到实际需要分析的代码。
malloc_zone_calloc 传入的 default_zone,执行 ptr = zone->calloc(zone, num_items, size)
defaultzone->calloc 实际的函数实现为 default_zone_calloc
通过控制台输出
p zone->calloc
得出调用nano_calloc
方法nano_calloc 的实现如下:
_nano_malloc_check_clear
源码进入
segregated_size_to_fit
加密算法源码, 通过算法逻辑,可以看出,其本质就会16字节对齐算法从源码中看到,传进来的size是40,SHIFT_NANO_QUANTUM是4,NANO_REGIME_QUANTA_SIZE就是16,那么这里就是16字节对齐,因为传进来的是40,为了能够16字节对齐需要补齐所以得到的就是48。从上面的对象的字节对齐是8字节,为什么系统开辟的内存是16字节呢?因为8字节对齐的参考的是对象里面的属性,而16字节对齐的参考的是整个对象,因为系统开辟的内存如果只是按照对象属性的大小来的话,可能会导致内存溢出的。
The text was updated successfully, but these errors were encountered: