查看一个NSObject对象占用多少内存

1、引入头文件:

#import <objc/runtime.h>

#import <malloc/malloc.h>

2、代码如下:

  1. NSObject* obj = [[NSObject alloc]init];
  2.  
  3. // 获取实例对象至少需要分配的内存大小,实际真正占用的大小,8 字节
  4. size_t insSize = class_getInstanceSize([NSObject class]);
  5. NSLog(@"NSObject Size:%zd",insSize);
  6. // 同上
  7. insSize = class_getInstanceSize([obj class]);
  8. NSLog(@"NSObject Size:%zd",insSize);
  9.  
  10. // 获取实际分配内存大小,最终分配的大小,16 字节
  11. size_t mSize = malloc_size((__bridge const void *)obj);
  12. NSLog(@"malloc Size:%zd",mSize);
  13.  
  14. // 通过OC的源码可以看出配置对象内存至少有 16字节

  1>、通过 class_getInstanceSize 可以获取类对象实际占用的大小

  2>、通过 malloc_size 实际分配内存大小,最终分配的大小

如下是OC的源码,可以看得出如果分配的内存小于16的话会直接设置为16

可以通过内存查看工具来验证上面的说法:

进入Debug模式,通过 Debug -> Debug Workfllow -> View Memory (Shift + Command + M)  可以打开内存查看工具

1、进入调试模式,断点代码后,通过 po 对象,可以查看对象对应的地址

  

  1. (lldb) po obj
  2. <NSObject: 0x1002013d0>

2、在下面Address输入框输入要查看的内存地址,回车就可查看

通过上面的截图可以看到被选中的那个8个字节都是00,都是空的,说明根本就没有用到,实际只用到了前面的8字节

为什么就可以这么肯定它占用了16个字节呢?因为可以看出00后面就是 03 00 00 00  了,系统内存分配都是连续一段的,中间是不会有间隙的,所以可以确定系统就是分配了 16个字节

3、也可以通过 x 命令来查看,命令如下:

  1. (lldb) x 0x1002013d0
  2.  
  3. 0x1002013d0: f1 f0 7c ff ff 1d 00 00 00 00 00 00 00 00 ..h|............
  4.  
  5. 0x1002013e0: ...............

一样可以看得出后8位都是00

查看自定义对象的内存占用大小

  1. @interface XGPerson : NSObject
  2.  
  3. @property (nonatomic,assign) int age;
  4. @property (nonatomic,assign) int height;
  5. @property (nonatomic,assign) int row;
  6.  
  7. @end
  8.  
  9. @implementation XGPerson
  10.  
  11. @end

像上面这个对象,里面有3个属性,都是int ,每个int类型是占4字节的,具体其它类型占多少可以去查官方文档

同过如下代码进行测试:

  1. XGPerson* obj = [[XGPerson alloc]init];
  2. obj.age = ;
  3. obj.height = ;
  4. obj.row = ;
  5.  
  6. // 输出:24字节
  7. size_t insSize = class_getInstanceSize([XGPerson class]);
  8. NSLog(@"XGPerson Size:%zd",insSize);
  9.  
  10. // 输出:32字节
  11. size_t mSize = malloc_size((__bridge const void *)obj);
  12. NSLog(@"malloc Size:%zd",mSize);

再通过上面说的那种内存查看方法去看看内存

  1. (lldb) po obj
  2. <XGPerson: 0x100602ed0>
  3.  
  4. (lldb) x 0x100602ed0
  5. 0x100602ed0: d9 12 00 00 1d 04 00 00 00 05 00 00 00 ................
  6. 0x100602ee0: 06 00 00 00 ................

通过内存打印,可以看得出3个属性分别各自占用了4个字节,总共是24个,那为什么 malloc_size 会输出32个呢?

原因就是系统底层的内存对齐导致的 (内存对齐好像分配的16的倍数,像24不是16的倍数,所以被分配32,不知道我理解的对不对,请各位大神指点!)

通过上面这个输出日志可以看得出,如果我们这个XGPerson只有2个属性,那它的分配大小和实际占用大小应该都是16,因为NSObject对象默认只用到了前8个字节

所以只有当有3个属性的时候才会变成32个字节。

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

本文参考借鉴MJ的教程视频,非常感谢.





【OC底层】一个OC对象占用多少内存?的更多相关文章

  1. [转]new一个Object对象占用多少内存?

    我们分解下ArrayList arr = new ArrayList();等同于ArrayList arr = null;//初始化arr = new ArrayList();//实例化这两个过程.初 ...

  2. new一个Object对象占用多少内存?

    Java的自动内存管理机制省却了很多编码工作,大大地提高了Java的生产力,而且JVM的性能也越来越好,特别是G1的出现,改善了垃圾回收中stop the world的状况. 也许很多人都没有考虑过这 ...

  3. 探索一个NSObject对象占用多少内存?

    1 下面写代码测试探索NSObject的本质 Objective-C代码,底层实现其实都是C\C++代码 #import <Foundation/Foundation.h> int mai ...

  4. 高端面试必备:一个Java对象占用多大内存

    这个问题一般会出现在稍微高端一点的 Java 面试环节.要求面试者不仅对 Java 基础知识熟悉,更重要的是要了解内存模型. Java 对象模型 HotSpot JVM 使用名为 oops (Ordi ...

  5. java.lang.instrument: 一个Java对象占用多少字节?

    一.对象头包括两部分信息:Mark Word(标记字段)和 Klass Pointer(类型指针)   1. Mark Word 用于存储对象自身的运行时数据,如哈希码(HashCode).GC分代年 ...

  6. python统计某一个进程名所占用的内存

    设计思路: 通过python,执行cmd中tasklist命令,获取要统计的进程的相关信息:通过正则表达式,查找出进程名称.进程pid.内存使用,然后打印出来. 作为pythoner,有时候需要统计p ...

  7. 【OC底层】OC对象本质,如 isa, super-class

    Objective-C的本质 1.我们编写的Objective-C,底层现实都是C/C++,代码生成步骤如下:   2.在OC中的所有面向对象的实现,都是基于C/C++的数据结构实现的 3.将Obje ...

  8. 如果对象的引用被置为null,;垃圾回收器是否会立即释放对象占用的内存?

    不会,在下一个垃圾回调周期中,这个对象将是被可回收的. 也就是说并不会立即被垃圾收集器立刻回收,而是在下一次垃圾回收时才会释放其占用的内存.

  9. 如何获取一个Java对象所占内存大小

    新建一个maven工程 我们先在IDEA中新建一个名为ObjectSizeFetcherAgent的maven工程,如下图: 在maven项目中的pom.xml中新增一个打jar包的插件,如下: &l ...

随机推荐

  1. 单选按钮(RadioButton)

    一:RadioButton的相关属性: 1.Activity //单选按钮 public class RadioButtonActivity extends Activity { private Co ...

  2. 第十五章——自编码器(Autoencoders)

    自编码器是一种能够通过无监督学习,学到输入数据高效表示的人工神经网络.输入数据的这一高效表示称为编码(codings),其维度一般远小于输入数据,使得自编码器可用于降维(查看第八章).更重要的是,自编 ...

  3. 自学git心得-4

    本节介绍分支的一些具体应用实例. 1.Bug分支 设想我们正在分支dev上工作,突然接到一个修复bug的命令,我们需要创建分支issue-101来修复它,在此之前我们肯定需要先保存我们当前未完成的工作 ...

  4. python的逻辑运算符

    函数就是特殊的变量(这个变量是不加引号的)  我们 如果直接打印一个函数的名字是直接打印这个函数的内存地址 python的运算符: 首先Python的运算符和其他语言的运算符都是一样的  都有:算数运 ...

  5. MySQL -Naivacat工具与pymysql模块

    Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库. 官网下载:https ...

  6. @Autowired和@Resource注解的区别

    @Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false.如果我们想使用按名称装配,可以结合@Qualifier注 ...

  7. 沉淀,再出发:结合案例看python

    沉淀,再出发:结合案例看python 一.前言 关于python,如果不经过大型程序开发的洗礼,我们很难说自己已经懂得了python了,因此,我们需要通过稍微结构化的编程来学习python. 二.一个 ...

  8. Windows Server、 Windows 区别

    今天脑补了普通Windows 操作系统与Windows Server区别,感觉清楚了很多. Microsoft WindowsServer,是美国微软公司研制的一套操作体系,它面世于1985年,起先仅 ...

  9. GO语言 切片的缩短和增长原理

    package main import "fmt" //import OS "os" //import "strings" //import ...

  10. css根据屏幕大小切换样式

    首先html head之间加入: <meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0, ma ...