当前位置: 首页 > news >正文

objective-c内存管理基础

    对于我们.net开发人员来说,.net为我们提供了自动内存管理的机制,我们不需去关心内存的管理。但是iphone开发中却是不能的。这篇文章将简述一下objective-c的内存管理机制和方法和一些特性。

   手动的进行内存管理

    Cocoa和Objective-C的类都是NSObject的子类。NSObject中有几个方法进行内存管理。alloc方法为对象分配一片内存空间。dealloc方法用于释放对象的空间。但是在我们的代码中将永远都不会使用dealloc方法,因为运行时会为你调用此方法释放内存空间。而你需要做的只是引用计数,稍后介绍什么是引用计数。

    除了alloc和dealloc,NSObject的还有retain和release方法两个方法用于引用计数。retain方法给retainCount变量加1,release方法给retainCount变量减1。当使用alloc为对象分配一片内存空间的时候,retainCount会为1。在这个对象的生命周期内,这个对象可能继续被其它变量引用。但有新的变量指向这个对象的时候,你应该调用retain方法,这样运行时才会知道有新的引用指向了这个变量,在这个对象生存期中拥有它的使用权。这个被Objective-C开发人员称之为“拥有”。例如:

Foo * myFooOne = [[Foo alloc] init]; // retaincount 为1
Foo * myFooTwo = myFooOne; // myFooTwo 指向了这个对象
// retaincount 仍然为1
[myFooTwo retain]; // 调用retain方法,运行时才知道myFooTwo指向了该对象,retaincount 为2

   上面的代码中,myFooTwo通过调用retain方法,取得了Foo对象的拥有权。在这个对象的生命周期中,会有很多变量来指向和引用它。指向这个对象的变量也可以通过release方法来解除这种拥有权。release方法将会告诉运行时,我已经使用完这个变量了,已经不需要它了,retainCount计数减1。

    当对象的retainCount的计数大于或者等于1的时候,运行时会继续维持这个对象。当对象的retainCount为0的时候,运行时会释放这个对象,并回收它占得内存空间。

    下图展示了一个Foo对象的生命周期。Foo对象首先在内存中分配一个内存空间,并且被myFooOne引用。在这个时候Foo对象的retaincount为1。

Foo * myFooOne = [[Foo alloc] init];

   第二个引用变量指向Foo对象,这个引用变量接着调用retain方法,其实也是调用Foo对象的retain方法。Foo对象的retaincount变成2。

Foo * myFooTwo = myFooOne;
[myFooTwo retain];

   接着当myFooOne引用不需要的时候,通过调用release方法,解除与Foo对象的拥有权,Foo对象的retaincount变成1。

[myFooOne release];

    但myFooTwo不在需要的时候,同样通过调用release方法,解除与Foo对象的拥有权,Foo对象的retaincount变成0。

   内存泄露

    我们经常会在一个方法中声明对象,看下面这个例子:

- ( void ) myMethod {
// incorrect method
NSString * myString = [[NSString alloc] init]; // retainCount = 1
Foo * myFoo = [[Foo alloc] initWithName:myString]; // retainCount = 1
NSLog( @" Foo's Name:%@ " , [myFoo getName]);
}

    这上面这个方法中,我们为myString 和myFoo分配了内存空间。方法执行结束之后,两个变量超出了作用域的范围,所以不再有效。但是这个方法并没有releases这两个对象。所以运行时没有释放这两个变量占据的内存空间。除非你的应用程序结束,否则这两个变量占据的内存空间一直都是不可用的。我们把它称之为内存泄露。

    为了防止内存泄露。无论什么时候,我们创建一个对象,或者创建一个对象的拷贝,我们都必须通过release方法释放。

- ( void ) myMethod {
NSString
* myString = [[NSString alloc] init]; // retainCount=1
Foo * myFoo = [[Foo alloc] initWithName:myString]; // retainCount=1
NSLog( " Foo's Name:%@ " , [myFoo getName]);
[myFoo release];
// retainCount=0 so deallocate
[myString release]; // retainCount=0 so deallocate
}

  弱引用

   看下面的例子:

- ( void ) myMethod {
// an incorrect method
Foo * myFooOne = [[Foo alloc] initWithName: @" James " ]; // retainCount=1
Foo * myFooTwo = myFooOne; // retainCount still 1
[myFooOne release]; // retaincount=0 so deallocated
NSLog( " Name:%@ " , [myFooTwo printOutName]); // runtime error
}

nyFooTwo指向了Foo对象,但是没有调用retain方法,就是一种弱引用,上面的代码会在运行时报错。因为myFooOne调用release方法。retaincount变成0,运行时,回收了对象的内存空间。然后myFooTwo调用printPutName自然就报错了,见下图说明。

总结:本文简单的介绍了一下手动的进行内存管理、内存泄露、弱引用等objective-c的知识。



(全文完)


以下为广告部分

您部署的HTTPS网站安全吗?

如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!

SSL检测评估

快速了解HTTPS网站安全情况。

安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。

SSL证书工具

安装部署SSL证书变得更方便。

SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。

SSL漏洞检测

让服务器远离SSL证书漏洞侵扰

TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。

相关文章:

  • Windows API一日一练(54)WriteFile和ReadFile函数
  • 关于应用系统的性能优化
  • 嵌入式WEB中CGI调用另外的html
  • Web系统下Office文档的处理 之OpenXML基础
  • C# 事件与委托
  • 细说Linux系统优化-实践篇
  • C# Timer用法
  • 2011年3月四级网络工程师试卷、答案及考点解析
  • ubuntu 9.04下安装NS2
  • SQL Server代理服务无法启动的处理方法(转载)
  • PXE脚本
  • 系统指令
  • 隆文互动营销研究院服务的企业微博再创新高
  • JAVA闭包
  • Dell PowerEdge 服务器操作系统部署速度比同类产品快我们是怎样利用生命周期控制器做到这点的呢?...
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • express如何解决request entity too large问题
  • JDK9: 集成 Jshell 和 Maven 项目.
  • JS实现简单的MVC模式开发小游戏
  • MySQL-事务管理(基础)
  • Objective-C 中关联引用的概念
  • React组件设计模式(一)
  • spring学习第二天
  • storm drpc实例
  • XForms - 更强大的Form
  • 关于字符编码你应该知道的事情
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 深度学习在携程攻略社区的应用
  • 说说动画卡顿的解决方案
  • 学习ES6 变量的解构赋值
  • 一个JAVA程序员成长之路分享
  • 进程与线程(三)——进程/线程间通信
  • ​2021半年盘点,不想你错过的重磅新书
  • #Z2294. 打印树的直径
  • (2)(2.10) LTM telemetry
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)甲方乙方——赵民谈找工作
  • **PHP二维数组遍历时同时赋值
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .gitignore文件—git忽略文件
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net framework 4.0中如何 输出 form 的name属性。
  • .net 生成二级域名
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .NET学习教程二——.net基础定义+VS常用设置
  • :如何用SQL脚本保存存储过程返回的结果集
  • @Pointcut 使用
  • [.NET]桃源网络硬盘 v7.4
  • [Angular] 笔记 8:list/detail 页面以及@Input
  • [BJDCTF 2020]easy_md5
  • [Hibernate] - Fetching strategies
  • [iOS]GCD(一)