`

静态全局变量的内存问题

 
阅读更多

来源:http://blog.csdn.net/pjk1129/article/details/6456982

 

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

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

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

 

项目中有时需要一些全局变量存储应用程序运行过程中的一直存在的信息,翻看了一些资料,决定使用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:一段

分享到:
评论

相关推荐

    CC++中的静态全局变量,静态局部变量,全局变量,局部变量的区别

    根据给定的文件信息,我们将深入探讨全局变量、局部变量、静态全局变量及静态局部变量之间的区别,以及`static`关键字在面向过程与面向对象编程中的不同应用。 ### 面向过程设计中的`static` #### 全局变量 全局...

    全局变量、局部变量、静态全局变量、静态局部变量的区别

    4. **可见性**:静态全局变量虽然具有全局作用域,但其可见性仅限于声明它的源文件,避免了全局变量可能带来的命名冲突问题。 理解这些变量类型的特性对于编写清晰、模块化和健壮的代码非常重要。正确地使用它们...

    全局变量、静态全局变量、静态局部变量和局部变量的区别2.pdf

    按照存储区域来划分,全局变量、静态全局变量和静态局部变量都存放在内存的全局数据区(也称为静态存储区),而局部变量则存放在内存的栈区。 1. **全局变量**:在程序的整个执行过程中始终存在,即使在函数调用...

    局部变量、全局变量、堆、堆栈、静态和全局

    静态全局变量只在定义它的源文件内可见,避免了全局变量的命名冲突,且其生命周期贯穿整个程序运行期间。 静态函数与普通函数的主要区别在于,静态函数只能在其定义的源文件内部被调用,提供了一种封装机制,防止...

    全局变量、局部变量、静态变量即内存管理

    从分配内存空间看,全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量...

    静态全局变量 静态数据成员 静态顺序栈.rar

    在C++编程中,"静态"一词有多种含义,主要涉及到静态全局变量、静态数据成员和静态成员函数。这些特性在程序设计中扮演着重要角色,尤其在数据结构和算法实现时。以下是对这些概念的详细解释: 1. 静态全局变量: ...

    定义全局变量 变量 全局

    总结起来,MFC工程中的全局变量和函数可以通过将它们作为应用程序类的成员或使用静态成员来实现。前者可能需要额外的访问步骤,而后者提供了更直接的访问方式。根据项目需求和代码结构,开发者可以选择最适合的方法...

    C++中类使用全局变量

    2. **初始化**:全局变量在程序开始时自动初始化,对于非静态全局变量,如果未指定初始值,它们将被初始化为零或垃圾值。对于静态全局变量,它们只在首次访问时初始化。 3. **作用域**:全局变量在整个程序中可见,...

    C语言面试题大汇总之华为面试题:1、局部变量能否和全局变量重名;2、如何引用一个已经定义过的全局变量;3、全局变量可不可以定义在可被多个.C文件包含的头文件中 为什么;4、语句for( ;1 ;)有什么问题 它是什么意思……

    静态全局变量的作用域限制在定义该变量的源文件内,避免在其它源文件中引起错误。static 局部变量只被初始化一次,下一次依据上一次结果值。static 函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。 六...

    QT 使用全局变量的方法 - 郭小郭的专栏 - CSDN博客1

    2. **内存管理**:全局变量的生命周期始于程序启动,结束于程序结束,可能导致资源泄漏。 3. **命名空间**:为了避免命名冲突,可以使用命名空间来组织全局变量。 4. **使用静态成员**:如果确实需要全局变量,优先...

    全局 局部变量以及static 变量区别

    - 当设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需考虑重入问题。 - 为了创建可重入的函数,应避免在函数中使用`static`变量。 - **特殊用途**: - 当函数返回值为指针类型时,通常使用...

    全局变量的使用

    9. **静态全局变量**:如果全局变量前加上`static`关键字,那么它将只在当前源文件内可见,这就是所谓的静态全局变量,它的生命周期仍然从程序开始到结束,但作用域限制在定义它的源文件内。 理解并合理使用全局...

    VC中的全局变量.doc

    - **生命周期**:全局变量的生命周期从程序开始到结束,这意味着它们在整个程序运行期间一直存在,可能导致内存泄漏或意外修改。 - **可见性**:全局变量对所有文件都是可见的,除非通过`extern`声明进行了限制。...

    C语言中静态和全局的区别

    而静态全局变量的作用域被限定在声明它的文件内部,其他文件无法访问,这可以避免变量名冲突的问题。 静态变量分为静态局部变量和静态全局变量。静态局部变量的作用域是局部的,类似于自动变量,但是其生命周期贯穿...

    37_全局变量和局部变量的区别1

    - **静态全局变量**:静态全局变量限制了其文件外的可见性,只在其定义的源文件内部可用,具有内部链接性。 - **局部变量**:无论是静态还是非静态,局部变量都不具有外部链接性,不能在其他文件中直接访问。 ...

    C语言学习之静态变量

    静态变量主要分为两类:静态局部变量和静态全局变量。 1. **静态局部变量**: - 静态局部变量使用`static`关键字在函数内部定义,其生命周期贯穿整个程序执行期间,但作用域仅限于定义它的函数内部。 - 与普通...

    C/C++ 跨文件共享全局变量Demo

    - **作用域和生命周期**:全局变量在整个程序的生命周期内都存在,可能导致内存泄漏和意外修改。 - **依赖性**:过度依赖全局变量会使代码难以理解和维护,因为它们可以无处不在地被修改。 - **线程安全**:在多线程...

    局部变量 全局变量 堆栈总结

    ### 局部变量与全局变量及其在堆栈中的管理 #### 一、基本概念 **局部变量(Local Variables)**:在函数或代码块...此外,适当使用静态变量可以帮助优化程序性能,但应注意避免滥用全局变量以防止潜在的数据冲突问题。

    C++中的局部变量、全局变量、局部静态变量、全局静态变量的区别

    需要注意的是,过多的全局变量可能导致命名冲突和难以追踪的问题。以下是一个全局变量的例子: ```cpp int nData = 10; // 这是一个全局变量,作用域是整个程序 int main() { // ... } ``` 3. 局部静态变量...

    局部变量与全局变量区别,栈、堆和静态存储区的区别[借鉴].pdf

    1. 若全局变量仅在单个文件中访问,则可以讲这个变量修改为静态全局变量。 2. 若全局变量仅在单个函数中使用,则可以将这个变量修改为该函数的静态局部变量。 3. 全局变量、静态局部变量、静态全局变量都存放在静态...

Global site tag (gtag.js) - Google Analytics