初学Objective-C的朋友都有一个困惑,总觉得对Objective-C的内存管理机制琢磨不透,程 序经常内存泄漏或莫名其妙的崩溃。我在这里总结了自己对Objective-C内存管理机制的研究成果和经验,写了这么一个由浅入深的教程。希望对大家有 所帮助,也欢迎大家一起探讨。

系统自动创建新的autorelease pool

在生成新的Run Loop的时候,系统会自动创建新的autorelease pool(非常感谢网友hhyytt和neogui的提醒)。注意,此处不同于xcode在新建项目时自动生成的代码中加入的autorelease pool,xcode生成的代码可以被删除,但系统自动创建的新的autorelease pool是无法删除的(对于无Garbage Collection的环境来说)。Objective-C没有给出实现代码,官方文档也没有说明,但我们可以通过小程序来证明。

在这个小程序中,我们先生成了一个autorelease pool,然后生成一个autorelease的ClassA的实例,再在一个新的run loop中生成一个autorelease的ClassB的对象(注意,我们并没有手动在新run loop中生成autorelease pool)。精简的示例代码如下,详细代码请见附件中的memman-run-loop-with-pool.m。

  1. int main(int argc, char**argv)
  2. {
  3. NSLog(@"create an autorelasePool\n");
  4. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  5. NSLog(@"create an instance of ClassA and autorelease\n");
  6. ClassA *obj1 = [[[ClassA alloc] init] autorelease];
  7. NSDate *now = [[NSDate alloc] init];
  8. NSTimer *timer = [[NSTimer alloc] initWithFireDate:now
  9. interval:0.0
  10. target:obj1
  11. selector:@selector(createClassB)
  12. userInfo:nil
  13. repeats:NO];
  14. NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
  15. [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
  16. [timer release];
  17. [now release];
  18. [runLoop run]; //在新loop中调用一函数,生成ClassB的autorelease实例
  19. NSLog(@"releasing autorelasePool\n");
  20. [pool release];
  21. NSLog(@"autorelasePool is released\n");
  22. return 0;
  23. }

输出如下:

create an autorelasePool

create an instance of ClassA and autorelease

create an instance of ClassB and autorelease

ClassB destroyed

releasing autorelasePool

ClassA destroyed

autorelasePool is released

注意在我们销毁autorelease pool之前,ClassB的autorelease实例就已经被销毁了。

有人可能会说,这并不能说明新的run loop自动生成了一个新的autorelease pool,说不定还只是用了老的autorelease pool,只不过后来drain了一次而已。我们可以在main函数中不生成autorelease pool。精简的示例代码如下,详细代码请见附件中的memman-run-loop-without-pool.m。

  1. int main(int argc, char**argv)
  2. {
  3. NSLog(@"No autorelasePool created\n");
  4. NSLog(@"create an instance of ClassA\n");
  5. ClassA *obj1 = [[ClassA alloc] init];
  6. NSDate *now = [[NSDate alloc] init];
  7. NSTimer *timer = [[NSTimer alloc] initWithFireDate:now
  8. interval:0.0
  9. target:obj1
  10. selector:@selector(createClassB)
  11. userInfo:nil
  12. repeats:NO];
  13. NSRunloop *runLoop = [NSRunLoop currentRunLoop];
  14. [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
  15. [timer release];
  16. [now release];
  17. [runLoop run]; //在新loop中调用一函数,生成ClassB的autorelease实例
  18. NSLog(@"Manually release the instance of ClassA\n");
  19. [obj1 release];
  20. return 0;
  21. }

输出如下:

No autorelasePool created

create an instance of ClassA

create an instance of ClassB and autorelease

ClassB destroyed

Manually release the instance of ClassA

ClassA destroyed

我们可以看出来,我们并没有创建任何autorelease pool,可是ClassB的实例依然被自动销毁了,这说明新的run loop自动创建了一个autorelease pool,这个pool在新的run loop结束的时候会销毁自己(并自动release所包含的对象)。

补充说明

在研究retain count的时候,我不建议用NSString。因为在下面的语句中,

  1. NSString *str1 = @”constant string”;

str1的retain count是个很大的数字。Objective-C对常量字符串做了特殊处理。

当然,如果你这样创建NSString,得到的retain count依然为1

  1. NSString *str2 = [NSString stringWithFormat:@”123”];

示例代码文件链接:http://files.cnblogs.com/VinceYuan/objective-c-memman.zip

Objective-C内存管理教程和原理剖析(四)的更多相关文章

  1. iPhone/Mac Objective-C内存管理教程和原理剖析

    http://www.cocoachina.com/bbs/read.php?tid-15963.html 版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所 ...

  2. Objective-C内存管理教程和原理剖析(三)

    初学Objective-C的朋友都有一个困惑,总觉得对Objective-C的内存管理机制琢磨不透,程 序经常内存泄漏或莫名其妙的崩溃.我在这里总结了自己对Objective-C内存管理机制的研究成果 ...

  3. Objective C内存管理之理解autorelease------面试题

    Objective C内存管理之理解autorelease   Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的A ...

  4. Objective C 内存管理[转]

    1  配对原则 alloc – release new – release retain - release copy – release 2  new和alloc-init的区别 (1)区别只在于a ...

  5. C++动态内存管理与源码剖析

    引言 在本篇文章中,我们主要剖析c++中的动态内存管理,包括malloc.new expression.operator new.array new和allocator内存分配方法以及对应的内存释放方 ...

  6. 内存管理cpuset,mempolicy[原理]

    介绍cpuset,mbind,set_mempolicy在内存管理上的应用 change log :确定先从mempolicy的man 手册翻译开始研究,计划如下 .先从man手册入手,通过实现mem ...

  7. objective C 内存管理及属性方法具体解释

    oc为每一个对象提供一个内部计数器.这个计数器跟踪对象的引用计数,当对象被创建或拷贝时.引用计数为1.每次保持对象时,调用retain接口.引用计数加1.假设不需要这个对象时调用release,引用计 ...

  8. Linux用户管理 权限管理 内存管理 网络管理命令 (第四天)

    默认添加的用户会自动加入和用户名一样的组中su 切换用户查看当前登陆的用户: whoami id`查看当前用户属于哪个组:groupsgroupadd 组名 添加组groupdel 组名 删除组gre ...

  9. mybatis教程之原理剖析

    MyBatis是目前非常流行的ORM框架,功能很强大,然而其实现却比较简单.优雅.本文通过代理的方式来看下其实现 方式一:传统API方式 @Test public void add() throws ...

随机推荐

  1. org.springframework.context.event.AbstractApplicationEventMulticaster

    private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType e ...

  2. iOS中如何呼出另一个应用

    我们经常会遇到在一个应用里面呼出另一个应用的需求,比如在文档里面点击地址,调用safari来打开网页:比如在文件浏览器里面点击某种文件,自动激活一个应用来打开文件. iOS里面对于这样的需求使用URL ...

  3. 利用boost做string到wstring转换,以及字符集转换 - Error - C++博客

    利用boost做string到wstring转换,以及字符集转换 - Error - C++博客 利用boost做string到wstring转换,以及字符集转换 #include <boost ...

  4. linux(debian) 安装jdk

    #vi /etc/profile 在里面添加如下内容 export JAVA_HOME=/usr/java/jdk1.6.0_27 export JAVA_BIN=/usr/java/jdk1.6.0 ...

  5. C#获取单个字符的拼音声母

    public class ConvertToPinYing     {         /// <summary>         /// 汉字转拼音缩写         /// < ...

  6. Web API Login with Cookie

    public HttpWebResponse InitiliazeWebRequest() { string responseData =string.Empty;//string url = Get ...

  7. 扑克k,你知道的人物吗?

    在扑克牌中,黑桃K——大卫王(以色列联合王国第二任国王):红桃K——查里曼大帝(法兰克国王,后加冕为罗马人的皇帝):梅花K——亚历山大大帝(马其顿帝国国王):方块K——凯撒大帝(罗马共和国终生执政官) ...

  8. wcf系列学习5天速成——第四天 wcf之分布式架构

    今天是wcf系列的第四天,也该出手压轴戏了.嗯,现在的大型架构,都是神马的, nginx鸡群,iis鸡群,wcf鸡群,DB鸡群,由一个人作战变成了群殴....... 今天我就分享下wcf鸡群,高性能架 ...

  9. gtest的Linux使用(Google test)

    GTest是Google开发的跨平台而且开源的C++单元测试框架,很好很强大. 下载地址:https://code.google.com/p/googletest/ . 关于GTest在Windows ...

  10. leetcode Swap Nodes in Pairs python

    # Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = ...