iOS中引用计数内存管理机制分析
在 iOS 中引用计数是内存的管理方式,虽然在 iOS5 版本中,已经支持了自动引用计数管理模式,但理解它的运行方式有助于我们了解程序的运行原理,有助于 debug 程序。
操作系统的内存管理分成堆和栈。
在堆中分配的内存,都试用引用计数模式;在栈中则不是。
NSString 定义的对象是保存在栈中,所以它没有引用计算。看一些书上说它的引用计算会是 fffffffff 最大整数,测试的结果显示它是- 1. 对该对象进行 retain 操作,不好改变它的 retainCount 值。
MutableNSString 定义的对象,需要先分配堆中的内存空间,再初始化才能使用。它是采用引用计数管理内存的。对该对象做 retainCount 操作则每次增加一个。
其实,引用计数是对内存区域的空间管理方式,是应从内存块的视角去看的。任何对象都是指向它的指针,有多少个指针指向它,就有多少个引用计算。
如果没有任何指针指向该内存块了,很明显,该内存块就没有对象引用了,引用计算就是 0, 系统会人为该内存区域已经空闲,于是立即清理,也就是更新一下管理堆的链表中某个标示位。
(miki西游 @mikixiyou 原文 链接: http://mikixiyou.iteye.com/blog/1592958 )
测试方法如下:
在 xcode 中建立一个非 arc 的项目,单视图即可。建立一个按钮的操作方法。
- (IBAction)testRC:(id)sender {
NSInteger i;
i=self.i_test;
if((i%2)==1)
{
NSString * str1=@"welcome";
NSString * str2=@"mlgb";
NSString * str3;
NSString * str4=@"welcome";
NSLog(@"str1 addr is %p",str1);
NSLog(@"str2 addr is %p",str3);
NSLog(@"str3 addr is %p",str3);
NSLog(@"str4 addr is %p",str4);
NSLog(@"str1 retainCount is %i",[str1 retainCount]);
NSLog(@"str2 retainCount is %i",[str2 retainCount]);
//NSLog(@"str3 retainCount is %i",[str3 retainCount]); 该使用会导致 crash ,因为 str3 没有指向任何内存区域。
str3=[str1 retain];
NSLog(@"str3=[str1 retain];");
NSLog(@"str1 retainCount is %i",[str1 retainCount]);
NSLog(@"str3 retainCount is %i",[str3 retainCount]);
str3=[str2 retain];
NSLog(@"str3=[str2 retain];");
NSLog(@"str2 retainCount is %i",[str1 retainCount]);
NSLog(@"str3 retainCount is %i",[str2 retainCount]);
/*
结果如下:
2012-07-14 11:07:38.358 testMem[878:f803] str1 addr is 0x3540
2012-07-14 11:07:38.360 testMem[878:f803] str2 addr is 0x0
2012-07-14 11:07:38.361 testMem[878:f803] str3 addr is 0x0
2012-07-14 11:07:38.362 testMem[878:f803] str4 addr is 0x3540
在栈中,内容相同的对象 str1 和 str4 ,都分配在一个内存区域中,这点是 c 编译器的功能,有利于内存使用和效率。
2012-07-14 11:07:38.363 testMem[878:f803] str1 retainCount is -1
2012-07-14 11:07:38.364 testMem[878:f803] str2 retainCount is -1
2012-07-14 11:07:38.365 testMem[878:f803] str3=[str1 retain];
2012-07-14 11:07:38.366 testMem[878:f803] str1 retainCount is -1
2012-07-14 11:07:38.367 testMem[878:f803] str3 retainCount is -1
2012-07-14 11:07:38.367 testMem[878:f803] str3=[str2 retain];
2012-07-14 11:07:38.368 testMem[878:f803] str2 retainCount is -1
2012-07-14 11:07:38.369 testMem[878:f803] str3 retainCount is -1
*/
}
else
{
NSMutableString * mstr1=[[NSMutableString alloc] initWithString: @"welcome" ];
NSMutableString * mstr2=[[ NSMutableString alloc ] initWithString : @"mlgb" ];
NSMutableString * mstr3;
NSMutableString * mstr4=[[ NSMutableString alloc ] initWithString : @"welcome" ];
NSLog( @"mstr1 addr is %p" ,mstr1);
NSLog( @"mstr2 addr is %p" ,mstr2);
NSLog( @"mstr3 addr is %p" ,mstr3);
NSLog( @"mstr4 addr is %p" ,mstr4);
NSLog( @"mstr1 retainCount is %i" ,[mstr1 retainCount]);
NSLog( @"mstr2 retainCount is %i" ,[mstr2 retainCount]);
//NSLog(@"mstr3 retainCount is %i",[mstr3 retainCount]);
mstr3=[mstr1 retain];
NSLog( @"mstr3=[mstr1 retain];" );
NSLog( @"mstr1 retainCount is %i" ,[mstr1 retainCount]);
NSLog( @"mstr3 retainCount is %i" ,[mstr3 retainCount]);
NSLog( @"mstr3 addr is %p" ,mstr3);
mstr3=[mstr2 retain];
NSLog( @"mstr3=[mstr2 retain];" );
NSLog( @"mstr2 retainCount is %i" ,[mstr1 retainCount]);
NSLog( @"mstr3 retainCount is %i" ,[mstr2 retainCount]);
NSLog( @"mstr3 addr is %p" ,mstr3);
/*
2012-07-14 11:07:36.652 testMem[878:f803] mstr1 addr is 0x68706b0
2012-07-14 11:07:36.655 testMem[878:f803] mstr2 addr is 0x6876040
2012-07-14 11:07:36.656 testMem[878:f803] mstr3 addr is 0x2a35
2012-07-14 11:07:36.657 testMem[878:f803] mstr4 addr is 0x686fbf0
2012-07-14 11:07:36.657 testMem[878:f803] mstr1 retainCount is 1
2012-07-14 11:07:36.658 testMem[878:f803] mstr2 retainCount is 1
2012-07-14 11:07:36.659 testMem[878:f803] mstr3=[mstr1 retain];
2012-07-14 11:07:36.660 testMem[878:f803] mstr1 retainCount is 2
2012-07-14 11:07:36.660 testMem[878:f803] mstr3 retainCount is 2
2012-07-14 11:07:36.661 testMem[878:f803] mstr3 addr is 0x68706b0
2012-07-14 11:07:36.662 testMem[878:f803] mstr3=[mstr2 retain];
2012-07-14 11:07:36.663 testMem[878:f803] mstr2 retainCount is 2
2012-07-14 11:07:36.663 testMem[878:f803] mstr3 retainCount is 2
2012-07-14 11:07:36.664 testMem[878:f803] mstr3 addr is 0x6876040
*/
}
self .i_test= self .i_test+ 1 ;
}
简而言之,引用计数实际上是指向其内存区域的指针数,从内存块的角度去理解,就很容易理解了。
iOS中引用计数内存管理机制分析的更多相关文章
- iOS 下ARC的内存管理机制
本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇 ...
- Keil C动态内存管理机制分析及改进(转)
源:Keil C动态内存管理机制分析及改进 Keil C是常用的嵌入式系统编程工具,它通过init_mempool.mallloe.free等函数,提供了动态存储管理等功能.本文通过对init_mem ...
- 初步swift语言学习笔记6(ARC-自己主动引用计数,内存管理)
笔者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/31824179 转载请注明出处 假设认为文章对你有所帮助.请通过留言 ...
- Keil C动态内存管理机制分析及改进
Keil C是常用的嵌入式系统编程工具,它通过init_mempool.mallloe.free等函数,提供了动态存储管理等功能.本文通过对init_mempool.mallloe和free这3个Ke ...
- memcached内存管理机制分析
memached是高性能分布式内存对象系统,通过在内存中存储数据对象来减少对磁盘的数据读取次数,提高服务速度. 从业务需求出发.我们通过一条命令(如set)将一条键值对(key,value)插入mem ...
- MRC、ARC内存管理机制
MRC下,oc内存管理遵循"谁创建.谁释放.谁引用.谁管理"的机制,当创建或引用一个对象时,需要向她发送alloc,copy,retain消息,当释放该对象时需要发送release ...
- 【深入理解Java虚拟机】自动内存管理机制——垃圾回收机制
Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...
- iOS内存管理机制解析之MRC手动引用计数机制
前言: iOS的内存管理机制ARC和MRC是程序猿參加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了. iOS内存管理机制发展史 iOS 5 ...
- 【python测试开发栈】python内存管理机制(一)—引用计数
什么是内存 在开始进入正题之前,我们先来回忆下,计算机基础原理的知识,为什么需要内存.我们都知道计算机的CPU相当于人类的大脑,其运算速度非常的快,而我们平时写的数据,比如:文档.代码等都是存储在磁盘 ...
随机推荐
- msql_DDL_创建table
• 语法: create table 表名(• 列名1 列类型 [<列的完整性约束>],• 列名2 列类型 [<列的完整性约束>],• ... ... ); • PRIMARY ...
- 一路踩过的坑 php
1.数据表唯一索引 (两列字段,组合索引) 遇到的情形:项目搭建新测试环境(其实就是所谓的灰度 与线上一致的一个环境):从线上拉回来代码搭建的,数据也是来自于线上数据,但是由于线上数据有部分为机密数 ...
- 如何使用 SQL Developer 导出数据
完成此方法文档后,您应该能够了解: 如何使用 SQL Developer 将数据导出为各种文件格式 如何导出模式中的对象定义 目录 1. 简介 2. 软件要求 3. 导出数据 4. 导出对象定义 5. ...
- 剑指Offer08 二进制中1的个数
/************************************************************************* > File Name: 08_NumOf1 ...
- Bootstrap基础学习-1
Bootstrap是一个基于栅格结构的前端结构框架(当然也有JS,JQuery),它的优点是内容框架能够迅速搭建起来,基于媒介查询可以使搭建的页面迅速的适应不同的用户端,无论是手机,平板,还是PC,基 ...
- 【CSS3】---为边框应用图片 border-image
为边框应用图片 border-image 顾名思义就是为边框应用背景图片,它和我们常用的background属性比较相似.例如: background:url(xx.jpg) 10px 20px no ...
- 实现类似微信的延迟加载的Fragment——LazyFragment
参考微信,使用ViewPager来显示不同的tab,每个tab是一个Fragment, 假设有3个tab,对应的fragment是FragmentA.FragmentB.FragmentC 需要实现的 ...
- (转)Android之自定义适配器
ListView作为一个实际开发中使用率非常高的视图,一般的系统自带的适配器都无法满足开发中的需求,这时候就需要开发人员来自定义适配器使得ListView能够有一个不错的显示效果. 有这样一个Demo ...
- asp.net 下载Excel (数据流,不保存)--客户端
效果图: 前端页面 <html> <head> <title>Test For Excel</title> <script src="j ...
- 在iOS中,实现点击搜索结果隐藏搜索结果的方法。
不知道有没有别的什么的好的方法,最近在实现一个需求(点击搜索,然后输入搜索内容,显示搜索出来的结果,然后点击搜索结果,在当前页面显示所点击的结果的详细的信息).遇到的问题是,点击搜索结果的时候,搜索的 ...