为什么 Objective-C 对象存储在堆上而不是栈上

Objective-C实现栈(附完整源码) 阅读详情

为什么 Objective-C 对象存储在堆上而不是栈上

一、什么是栈对象和堆对象

在Objective-C 中,对象通常是指一块有特定布局的连续内存区域。我们通常这样创建一个对象:

NSObject *obj = [[NSObject alloc] init];
这行代码创建了一个 NSObject 类型的指针 obj 和一个 NSObject 类型的对象,obj 指针存储在栈上,而其指向的对象则存储在堆上(简称为堆对象)。

目前 Objective-C 并不支持直接在栈上创建对象(简称为堆对象),但可以通过如下方式间接地创建:

struct {
Class isa;
} fakeNSObject;
fakeNSObject.isa = [NSObject class];

NSObject obj = (NSObject )&fakeNSObject;
NSLog(@”%@”, [obj description]);

栈对象 obj 也能正常工作,由此可见栈对象和堆对象都是可行的,但为什么 Objective-C 不默认使用栈对象呢?

二、栈对象优缺点

1、优点

速度

在栈上创建对象是非常快的,因为很多东西在编译时就确定了,运行时分配空间几乎不耗时;相对而言在堆上创建对象就非常耗时。

简单

栈对象的生命周期是确定的,对象出栈以后就会被释放,不会存在内存泄漏,但这同时也是栈对象的最大缺点。

2、缺点

生命周期固定

Objective-C 变量有效范围是由 “{}” 包含的块来决定的,也就是说栈对象的生命周期仅限于其所在的块里,出了块立马会被释放。一个对象被创建以后有可能会通过方法调用传递到别的方法,当栈对象的创建方法返回时,栈对象会被一起 pop 出栈而释放,导致其没法在别处被继续持有。此时 retain 操作会失效,除非用 copy 方法在想持有该栈对象的地方重新拷贝一份属于自己的栈对象。

因此,栈对象回给对象的内存管理造成相当大的麻烦。

空间

现代操作系统的栈和线程绑定,而栈空间是有限的,具体如下:

512 KB (secondary threads)
8 MB (OS X main thread)
1 MB (iOS main thread)
因此对象如果都在栈上创建不太现实,而堆只要物理内存不告警可以无限制使用。

综合以上优缺点,Objective-C 选择用堆存储对象。

三、真的没有栈对象吗

实际上 Objective-C 里的 block 却是栈对象,因此栈对象面临的问题在 block 身上一个都不少,但由于 block 是仅有的特殊对象,大家对它的特殊都已经习惯了,比如入行第一年的时候老师就告诉我们想持有一个 block 要用 copy 将 block 从栈拷贝到堆上。

另外,根据前面所说,栈对象的有效区域仅限于其所在的块,因此像下面的代码就无法输出期望的结果:

void (^block)();
if(x)
{
block = ^{ printf("x\n"); };
}
else
{
block = ^{ printf("not x\n"); };
}
block();

这也是大家需要特别注意的地方。

四、参考文档

Threading Programming Guide

Stack and Heap Objects in Objective-C

centos 添加新硬盘,对根目录扩容 本地安装了虚拟机,系统为centos7,使用过程中,渐渐地发现磁盘容量不够用了,于是在虚拟机中新增了一块硬盘。 进入系统内查看: sdb是新增的硬盘,大小为40g。 接下来有两种方式,一种是普通方式直接挂载。https://blog.youkuaiyun.com/qq_39314099/article/details/106200322 这样的话只有在挂载点的目录下操作才能使用到这个新硬盘,不是很理想。 还有一种方式lvm,逻辑卷管理的方式。 LVM简单介绍: 它是 Linux 下对磁盘分区进行管 阅读详情

相关推荐

Windows 11下WSL2安装CUDA避坑指南:从驱动版本匹配到环境变量配置

本文详细解析了在Windows 11的WSL2中搭建CUDA开发环境的完整流程与核心避坑要点。关键在于理解“驱动在Windows,工具链在Linux”的独特架构,并确保显卡驱动与CUDA Toolkit版本严格匹配。指南涵盖了从驱动验证、WSL-Ubuntu专用仓库安装、环境变量配置到GCC版本冲突、GPU算力不匹配等常见问题的解决方案,帮助开发者高效构建稳定的深度学习与高性能计算环境。

smartcontract5的博客 468

Object是引用数据类型,且只存储于堆(heap)中说法正确吗?(赋值、浅拷贝和深拷贝)

Object是引用数据类型,且只存储于堆(heap)中说法正确吗?(深拷贝浅拷贝)

cjn308408的博客 944

vcs覆盖率相关

选择要查看的覆盖率点,右键选择 show xxx tests;

qq_40571921的博客 2393

ios 栈和堆

一:一般认为在c中分为这几个存储区        1栈 - 由编译器自动分配释放        2堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收        3全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量              和未初始化的静态变量在相邻的另一块区域。 程序结束释放。

ygh5123687的博客 511

2021-08-20

通过QQ号获取绑定的手机号 导语 偶有奇想,我们可以通过手机号来搜索获取其对应的QQ号,那么,反过来呢? 一.缩小范围 由于手机号属于隐私数据,腾讯QQ并没有直接给出通过QQ号查找对应手机号的接口。 国内的手机号有十一位数字,从数学的角度上来说,包含了1011种可能。如果遍历这1011个数据,通过QQ中手机号查找QQ号的接口来寻找,未免太过费时费力,根据网上查到的资料,同一个QQ号,在十分钟内只能进行30次查询(未验证)。因此,直接遍历的方法不现实。 在这10^13个数据中,包含着大量的可去除的无用数据。我

m0_56063822的博客 4724

汽车电子开发必看:AUTOSAR MCAL层SPI驱动配置全解析(基于EB tresos)

本文深入解析了AUTOSAR MCAL层SPI驱动的核心配置,基于EB tresos工具详细阐述了通道、外部设备、作业与序列等关键概念。重点剖析了多设备共享总线时的资源管理与实时性调优策略,特别是SpiJobPriority参数的决定性影响,并提供了常见配置陷阱的实战排查指南,旨在帮助汽车电子工程师高效完成SPI驱动配置。

weixin_29188043的博客 293

IOS内存管理

1. 栈区(stack):由编译器自动分配释放,函数的参数值,局部变量等值。2. 堆区(heap):一般由开发人员分配释放,若不释放,则可能会引起内存泄漏。Objective-C提供了两种种内存管理方式:(MRC,手动引用计数器),(ARC,自动引用计数)。ARC作为苹果新提供的技术,苹果推荐开发者使用ARC技术来管理内存;

风·之痕的博客 8483

Nvidia Jetson 编解码开发(3)解决H265解码报错“PPS id out of range”

基于之前的开发程序通过Jetson Xavier NX 硬编码的H265发出后,上位机断点播放发出来的H265码流,会报“PPS id out of range” 错误。

jzwjzw19900922的博客 3812

iOS 堆和栈的区别?

前言 堆和栈是什么?有什么区别?是干嘛的?啥东西呀这是?别急,慢慢看下去 内存管理 移动设备的内存及其有限,每一个APP所能占用的内存是有限制的 (吐槽一下:iPhone6s还是16G起步,还好我也买不起->_-> 扯远了~~~) 什么行为会增加APP的内存占用 创建一个oc对象 定义一个变量 调用一个函数或者方法 内存管理范围 任何继承了NSObject的对象 对其它非对象类型无效 简单来说: 只有oc对象需要进行内存管理 非oc对象类型比如基本数据类型不需要进

u013712343的博客 2515

ATS Request中的PASID的作用是什么

摘要: PASID(进程地址空间标识符)是PCIe ATS(地址转换服务)中的关键组件,用于标识不同进程或虚拟机的地址空间。其主要作用包括:1)支持多进程共享设备时隔离地址空间;2)实现共享虚拟地址(SVA),允许用户态程序直接访问设备;3)提升虚拟化性能(如SIOV),通过PASID区分虚拟机请求;4)增强安全性,基于PASID限制设备内存访问权限。PASID通过20位标识符在TLP前缀中传递,与IOMMU协作完成地址转换与缓存,适用于高性能计算、AI及虚拟化场景,但依赖硬件支持和软件适配。

元直的博客 1562

海康VisionMaster与西门子PLC1200进行S7通信

通信是连通算法平台和外部设备的重要渠道,在海康VisionMaster算法平台中既支持外部数据的读入也支持数据的写出,当通信构建起来以后既可以把软件处理结果发送给外界,又可以通过外界发送字符来触发相机拍照或者软件运行。 本文以西门子PLC1200作为外部设备为例,讲解海康VisionMaster与西门子PLC1200进行S7通信。......

haier123888的博客 1万+

Objective-C 对象存储在堆上而不是栈上 why?

一、什么是栈对象和堆对象 在Objective-C 中,对象通常是指一块有特定布局的连续内存区域。我们通常这样创建一个对象: NSObject *obj = [[NSObject alloc] init]; 这行代码创建了一个 NSObject 类型的指针 obj 和一个 NSObject 类型的对象,obj 指针存储在栈上,而其指向的对象则存储在堆上(简称为堆对象)。 目前 Object...

LIN1986LIN的专栏 980

PCB仿真软件:Altium Designer_(15).AltiumDesigner的版本控制与项目管理

在进行PCB设计时,版本控制和项目管理是确保设计质量和团队协作效率的关键。Altium Designer 提供了强大的版本控制和项目管理功能,可以帮助设计团队更好地管理和维护项目。本节将详细介绍如何在Altium Designer中进行版本控制和项目管理,包括如何使用版本控制系统、如何管理项目文件、如何进行团队协作等。

kkchenjj的博客 1202

iOS底层原理系列02-深入了解Objective-C

对于自定义类,其内存结构会更复杂,包含从父类继承的变量和自己声明的变量。int _age;@end包含从NSObject继承的isa指针(8字节)包含一个int类型变量_age(4字节)包含一个double类型变量_height(8字节)包含一个NSString*类型的_name指针(由于@property自动合成,8字节)理论上总大小为:8 + 4 + 8 + 8 = 28字节。但实际分配会考虑内存对齐,可能会是32字节。特性+load调用时机程序启动加载类和分类时。

但行好事,莫问前程;不忘初心,方得始终! 3208

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

IOS objective-C(OC) block 详解

IOS objective-C(OC) block 详解,内容转自B站黑马课程的笔记 一.介绍 1.block是1个数据类型. BOOL、Boolean、class、nil、SEL、id、block。 2. block是一个数据类型. int double float char ....... 既然是1个数据类型,那么就可以声明这个数据类型的变量,所以我们完全可以声明1个block类型的变量. 不同类型的变量中可以存储不同类型的数据. 那么block类型的

weixin_42362496的博客 570

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++/Objective-C内存管理对比学习

C++内存管理内存分为五个区:堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈。存储函数中局部变量,函数结束时会自动释放。 堆。由new分配的内存块,由应用程序控制它的回收(需要手动回收),即一个new应该对应一个delete。如果程序员没释放,则程序结束系统会自动回收。 自由存储区。使用malloc分配的内存块,和堆类似,用free来释放。 全局/静态存储区。存放全局变量和静态变量。 常量存

来自星星的の松子的博客 999

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Objective-C 数据持久化

简介在开发通常需要我们把一些数据存储在本地,这篇我们来介绍iOS中数据持久化得方法。 1.属性列表 2.对象归档 3.偏好设置 4.嵌入式数据库(SQLite3) 5.苹果公司提供的持久化工具 Core Data 以下我们围绕这4种方式逐一介绍,在上一遍种我们介绍了“沙盒”和文件管理的基础知识,我们将以上一篇为基础进行介绍后面内容1.属性列表属性列表(plist),指定应用的配置比如tabbar的状

yanshi_hu的博客 1387

Objective-C基础(三)

而meta-class对象只存储类方法信息,因此meta-class的属性信息、协议信息、成员变量信息这些字段虽然存在,但是。sizeof是运算符,其返回值在编译期就已经决定了,例如如果传入的是一个bool类型的变量,就返回1,int返回4。,即这个结构体是可读写的,这也表明类的方法列表,属性列表,协议列表,是可读写的,这在之后的Runtime中会有相应的体现,大家可以先记住。如果对这个对象调用malloc_size方法,由于对象存储在堆上,因此需要做系统内存对齐(扩展为16的倍数),返回的结果为。

weixin_41994174的博客 222

Objective-C学习笔记——块(block)

Objective-C学习笔记——块(block) 1.理解块的概念 块的语法结构如下 return_type (^block_name)(parameters) 块在声明它的范围里,任何变量都会被其捕获,即在这个范围里的全部变量都可以在块中使用。默认情况下,块所捕获的变量是不可以在块之中修改的,否则编译器会报错。若想修改则需要在该变量声明时在声明前加上__block修饰符。 内联块(inline block):作为方法调用的块不赋值给局部变量而是直接内联在方法调用之中。OC在引入块这一特性之前需要通过传

weixin_43809624的博客 459

看看 Objective-C 里面 Class 和实例的数据结构

链接:https://juejin.cn/post/6912359669704949767 objc 源码下载地址 首先到苹果objc源码官网下载一个最新的包,这里下载的是 objc4-781.tar Class 和实例的数据结构 看一个例子 // ---------------- Animal ---------------- @interface Animal : NSObject { @public int _age; } - (void)run; // 实例方法 + (void)ani

henry_lei的博客 307

Objective C语法之NSArray

NSArray语法

飞在江湖的专栏 382

Objective-C 关联对象

关联对象是主要是解决在分类中无法保存成员变量的方法; 基本使用 因为category中没有存储成员变量的地方,所以只能通过关联对象的方式关联把对象和属性关联起来存储。 关联对象 在runtime中所存在的关联方法 typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) { OBJC_ASSOCIATION_ASSIGN = 0,...

wangchuanqi256的博客 463

effective-Objective-C 第一章阅读笔记

主要内容包括:1) OC采用消息结构而非函数调用,运行时决定执行代码;2) 内存管理采用引用计数机制,对象存储在堆/常量区;3) 类头文件应减少引用其他头文件,使用@class进行向前声明;4) 推荐使用字面量语法简化代码;5) 建议多用类型变量替代#define预处理指令;6) 枚举的使用技巧和优化方法

2501_91546205的博客 1385

【NSArray和NSDictionary的内存管理 Objective-C语言】

NSArray和NSDictionary的内存管理 Objective-C语言

madoca的博客 552

Objective-C Runtime(二)创建对象

分配对象地址,init是用来清除地址上的数据,使其初始化objc源码地址:https://opensource.apple.com/tarballs/objc4/ &person1代表的是当前指针的地址, 而person1则表示指针对象的地址,根据日志很容易得出 指针变量: 存储在栈区, 高 -》 低 排列 对象地址: 存储在堆区, 由低到高 Alloc具体实现 根据有如下几种方式创建类,最终调用了都指向了同一个方法 alloc执行顺序 NSObject创建 objc_alloc cal

jiodg45的博客 371

Objective-C中NSString对象的retainCount

综合上述内容: 1)对于通过initWithString和stringWithString(字面量)创建的NSString对象,不管字符串的内容和长度怎么变化,该对象始终是存储在常量区的,没有引用计数一说;硬要加一个引用计数的话,那么就是无符号长整型的最大值 2)对于通过initWithFormat和stringWithFormat创建的NSString对象,如果字符串内容是汉字,那么,该对象和Objective-C中其他类型的对象是一致的;如果字符串内容是非汉字,那么,当字符串长度小于10个时,该对象存储

MonkeyLu92的博客 1313
上一篇: iOS 神经网络
下一篇: 深入浅出理解视频编码H264结构
Philm_iOS
博客等级 码龄8年 74粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值