`

iphone开发内存管理──静态全局变量的内存问题

    博客分类:
  • ios
 
阅读更多

我们在项目中,有时需要一些全局变量存储一些基本信息,那么这些全局的变量内存又是如何管理的呢?

下面是网友分享的经验,具体的网址我记不清了,我在这里直接拿过来放到我的博客了,在此向写本文的作者致敬!

正是由于众多具有开源精神的网友,技术才能更好的传播!

 

项目中有时需要一些全局变量存储应用程序运行过程中的一直存在的信息,翻看了一些资料,决定使用Apple官方文档推荐的Signaleton模式,使用过程很顺利,但是随之而来的是关于内存管理的考虑,官方文档的示例代码如下:

static MyGizmoClass *sharedGizmoManager = nil;
+ (MyGizmoClass*)sharedManager {
    if (sharedGizmoManager == nil) {
        sharedGizmoManager = [[super allocWithZone:NULL] init];
    }
    return sharedGizmoManager;
}
+ (id)allocWithZone: (NSZone *)zone {
     return [[self sharedManager] retain];
}
- (id)copyWithZone: (NSZone *)zone {
     return self ;
}
- (id)retain {
     return self;
}
- (NSUInteger)retainCount {
     return NSUIntegerMax;  //denotes an object that cannot be released
}
- (void)release {
     //do nothing
}
- (id)autorelease {
     return self;
}
  可以看到上面的代码中除了为保证这个静态类的唯一性,还有一个奇怪的地方则是这个类没有dealloc方法,那么这个类实例化后所分配的内存是在什么时候释放的?如果这个类中还含有一些其他的成员变量,这些变量所分配的内存又是在何时释放的呢?

      以之前C/C++平台的经验,静态变量的内存被放在全局区(或称之为静态区),静态变量的内存在应用程序启动之前由系统分配,在应用程序退出之后又由系统自己回收。Cocoa基于C设计,所以大致上应该也是这个样子。

      为了验证这个问题,我尝试着给这个类添加了一个dealloc方法,之后更加奇怪的事情就发生了,我在这个类dealloc方法中设置断点并且尝试输出log,但当程序退出时不仅断点没有断下来,甚至在console中连这段log的踪影都看不到,我开始怀疑这段dealloc没有被调用,之后我又在其他类的dealloc方法中输出log,发现一个规律:dealloc方法在程序运行过程中随着类实例的释放会被调用,但是当直接退出程序时(按HOME键),所有的dealloc都不被调用。这就说明当应用退出的时候,Cocoa是不会调用实例的dealloc方法的,这是意味着什么呢?我猜想,可能Cocoa会在应用程序退出时自己回收所有的内存,并且不像C++那样去调用存在的类实例的析构方法?为证实这个猜想,google之,最终在Cocoa With Love和Apple的另一份官方文档中找到了答案,并证明我的这个猜测是正确的:

      官方文档中是这么解释的: " When an application terminates, objects may not be sent a dealloc message since the process’s memory is automatically cleared on exit—it is more efficient simply to allow the operating system to clean up resources than to invoke all the memory management methods." 大致的意思就是:当应用程序退出时,对象不会接受到一个dealloc消息,系统会自己清理所有的资源,Apple认为这样比去调用一个内存管理方法更有 效率。

      Cocoa With Love的Matt关于我提问的解答是这样的: "You don't need to free data from a singleton -- it lasts until the program quits, so the dealloc method will never be invoked. If you need to close a network connection, or something else that actually needs to be ended, you should do this in a "close" method and invoke the "close" method on the singleton in your applicationWillTerminate: method of your application delegate." 意思差不多和官方一样,应用退出时,dealloc方法不会被调用,并且他建议我避免在dealloc中去作网络或其他类似的必须终止的操作,而应该将这 些操作放在applicationWillTerminate:中,以确定这些操作被执行。

     呵呵,谢谢Matt,他的这个建议确实是非常有效果的,否则我的下一个问题肯定的是:那么一定得终止的操作放在哪里执行?

所以关于这个问题的研究暂时就告一段落了,得出的结论是: 
1.不用担心静态全局变量的内存的问题,系统会在应用程序结束之后,回收这些内存;
2.应用程序结束时会直接回收所有的程序运行中的资源,而不调用对象的dealloc方法;
3.不要将类似网络或文件的关闭(应该是任何)操作放在类的dealloc方法中执行;

 

当然这也只是告一段落了,由此我又产生了两个问题:
1.如果系统会在程序结束后回收所有的资源,那么是否基本不用考虑什么内存泄露的问题?内存泄露只会在程序运行过程中发生?即使发生了内存泄露,应用程序退出时,系统也会回收这些内存;
2.Cocoa如何实现这一套资源管理机制的呢?只以内存说,难道系统给应用程序指定一段内存,你应用程序分配的内存只会在这一段区域里,当应用程序退出之后,我系统就直接抹了这段内存?

这两个问题想请教tinyfool 和 robinlu,不知他们二位有没有时间。不过我的这个blog太丑了,我先把字弄大点.

文中参考资料:
1.Apple推荐Sinaleton方法的文档Cocoa Fundamental Guide:Cocoa Objects中Creating a Singleton Instance一节 这里还有中文的
2.Cocoa With Love中关于top-level data的话题:Singletons, AppDelegates and top-level data. 这里讨论还了你需要全局数据的条件,还提供了另外一个方法存放全局的数据:放置在AppDelegates中,并且讨论了这种方法的不妥之处,建议和我一样的新手可以拜读一下.
3.Apple解释应用程序退出时不调用dealloc方法的文档:Memory Management Programming Guide for Cococa:Object Ownship and DisposalDeallocating an Object一节的important:一段

分享到:
评论

相关推荐

    iphone全局变量配置

    在iOS开发中,全局变量和配置文件的管理是至关重要的,它们可以提高代码的复用性和维护性。本文将深入探讨如何在iPhone应用中设置全局变量以及如何访问配置文件。 全局变量是在整个应用程序中都可以访问的变量,...

    C语言之动态内存分配

    而未初始化的全局变量和静态变量则位于另一个相邻区域。 - 这些变量在整个程序运行期间都有效。 4. **常量区**: - 常量区专门用来存放常量,如字符串常量、整型常量等。 - 存储在常量区的数据不能被修改,这有...

    《精通iOS开发》第6版.中文完整带书签

    - **内存管理**:合理使用ARC(自动引用计数)机制避免内存泄漏。 - **多线程编程**:利用GCD(Grand Central Dispatch)或其他并发机制提高应用响应速度。 - **缓存策略**:实现有效的缓存机制减少网络请求次数。 ...

    iOS笔试题.docx

    在全局或静态变量前使用,表示该变量的作用域仅限于当前文件;在类方法前使用,表示这是类方法而非实例方法。 7. `#import`是Objective-C特有的,它处理头文件并避免重复导入,而`#include`是C/C++中的。`@class`...

    Objective学习笔记

    包括类的基本结构、内存管理、变量与数据类型、属性、导入头文件、方法调用与签名、静态成员、self关键字、坐标系、类前向声明、deallocate方法、nil与null的区别、类别、动态类型检查、异常处理、初始化方法、访问...

    iphone——Swift中文教程完整版

    - **全局变量和局部变量**: 全局变量在整个程序中都可见,局部变量只在其定义的作用域内可见。 - **类型属性**: 属于类型的属性,而不是属于特定实例的属性。 **2.11 方法** - **实例方法**: 作用于实例的方法。 -...

    Unity3D教程:Unity效能关键点2

    定期手动调用垃圾收集(`System.GC.Collect()`)有助于内存管理,但在CPU成本上可能会产生短暂的波动,但在实际设备上对FPS影响较小。 综上所述,这些关键点可以帮助开发者在Unity3D项目中实现更好的性能优化,提升...

    嵌入式系统期末考试试卷-习题.doc

    - **数据段**:用于存储已初始化的全局变量和静态变量。 - **堆栈段**:用于管理函数调用过程中的局部变量和函数参数等。 - **存放器段**并不属于进程内存布局的一部分。 #### 三、嵌入式系统的定义与应用场景 ...

    CocoaFundamentals.pdf

    - **实现方式:**在类内部控制实例的创建过程,通常使用私有构造函数和静态成员变量。 4. **观察者模式:** - **观察者的概念:**一种基于事件的模式,允许对象之间建立一对多依赖关系。 - **实现方式:**通过...

    DELPHI 扫二维码 FOR IOS

    3. **Barcode.dpr**:这是 Delphi 应用程序的主程序文件,包含项目的启动点和全局变量声明。在这里,它很可能包含了创建主窗体和初始化 ZBar 解码器的代码。 4. **Barcode.dproj**:这是 Delphi 项目的配置文件,...

    2015年C语言程序设计试卷1

    1. **生命周期与程序执行时间相同**:在C语言中,全局变量和静态局部变量的生命周期与其所在的程序执行时间相同,它们在程序开始时被初始化,直到程序结束才释放。而栈上的局部变量(非静态的)在函数调用时创建,在...

    Swift基础教程(含:背景标注)

    通过ARC(Automatic Reference Counting,自动引用计数)机制极大地简化了内存管理问题。此外,框架堆栈始终基于Cocoa构建,Objective-C也逐渐支持了块、集合字面量和模块等功能,使得框架能够在不进行深入改动的...

    设计模式面试题

    - Java提供了多种工具和技术来帮助开发人员处理这些问题,如`synchronized`关键字、`volatile`关键字以及`java.util.concurrent`包中的各种类和接口。 - 例如,`ThreadLocal`类可以为每个线程提供独立的副本,避免了...

    微信小程序 教程之WXSS

    `class`用于静态样式,多个样式类名之间用空格分隔,如`<view class="normal_view"></view>`。 - **选择器支持**: WXSS支持多种选择器,包括类选择器(`.class`)、ID选择器(`#id`)、元素选择器(`element`)、...

Global site tag (gtag.js) - Google Analytics