Cocoa内存管理-对象在我身上为零

Cocoa内存管理-对象在我身上为零,cocoa,memory-management,Cocoa,Memory Management,Mac OS X 10.6,Cocoa项目,带有保留/发布gc 我有一个函数: 迭代特定目录,扫描其中的子文件夹(包括嵌套的子文件夹),构建一个NSMutableString数组(每个找到的子文件夹路径一个字符串),然后返回该数组 e、 g.(为简洁起见,删除了错误处理) 调用函数在每个会话中仅获取一次阵列,并将其保留以供以后处理: static NSMutableArray *gFolderPaths = nil; ... gFolderPaths = ListAllSubFolder

Mac OS X 10.6,Cocoa项目,带有保留/发布gc

我有一个函数:

  • 迭代特定目录,扫描其中的子文件夹(包括嵌套的子文件夹),构建一个NSMutableString数组(每个找到的子文件夹路径一个字符串),然后返回该数组
e、 g.(为简洁起见,删除了错误处理)

调用函数在每个会话中仅获取一次阵列,并将其保留以供以后处理:

static NSMutableArray *gFolderPaths = nil;

...

gFolderPaths = ListAllSubFoldersForFolderPath(myPath);
[gFolderPaths retain];
在这个阶段,一切似乎都很好。[gFolderPaths count]返回找到的正确路径数,[gFolderPaths description]打印出所有正确的路径名

问题:

当我稍后使用gFolderPaths时(比如,下一次运行我的事件循环),我的断言代码(以及Xcode中的gdb)告诉我它是nil

在初始抓取之后,我没有以任何方式修改gFolderPaths,因此我认为我的内存管理已经失败,运行时正在释放gFolderPaths

我的假设/假设

在我将字符串添加到可变数组时,我不必保留每个字符串,因为这是自动完成的,但一旦数组从函数中移交给我,我就必须保留它,因为我不会立即使用它。这是正确的吗


非常感谢您的帮助。

对象不会“去
nil

static NSMutableArray *gFolderPaths = nil;
此声明声明
gFolderPaths
是一个变量,它包含指向NSMutableArray对象的指针。 您可以使用指向无对象的指针初始化它:
nil

这个初始化是有效的,并且有意义,因为您没有数组放在这里,但是使用
nil
指针初始化要比不初始化好得多,因为变量中存在一些随机指针。(这不能发生在
静态
变量上,因为
静态
变量被初始化为
nil
,但显式性很好,显式初始化是无害的。)

当我稍后使用
gFolderPaths
时(比如,下一次运行我的事件循环),我的断言代码(以及Xcode中的gdb)告诉我它是
nil

在那次初始抓取之后,我没有以任何方式修改
gFolderPaths
,因此我认为我的内存管理已经完成,运行时正在释放
gFolderPaths

否。运行时不释放对象。运行时是语言的一部分,<>代码>留存和<代码>发布<代码>是基础框架的一部分。该框架位于该语言之上

因此,您可能会猜测您或其他一些代码(例如,在框架中)释放了对象,您以前将其指针存储在
gFolderPaths

否。如果发生这种情况,
gFolderPaths
变量不会突然包含
nil
;它仍将包含指向同一对象的同一指针。如果这是对象死亡之前的最后一个版本,则
gFolderPaths
变量仍将包含指向同一个现已死亡的对象的相同指针

尝试记录指针(例如,使用
NSLog(@“%p”,gFolderPaths)
)将打印一个看起来有效的地址,例如
0x2381ab6780
。尝试记录对象(例如,使用
%@
)几乎肯定会崩溃,因为对象已死亡

事实并非如此。您说过您的断言和对调试器的命令显示
gFolderPaths
变量包含
nil

有两种明显的可能性:

  • 有东西重新分配给变量。您说您的代码没有重新分配给变量。其他人都不应该知道,所以这种可能性是极不可能的
  • 您从未将对象指针指定给变量。要么您指定了
    nil
    ,要么您从未指定任何内容。你说你正在记录一个数组,这个数组的指针被分配给了变量,并且描述被验证了,所以我们可以完全排除这种可能性。(记录计数在测试中并不可靠,因为
    [nil count]
    将成功返回0。)
  • 这导致了第三种可能性:

    三,您有两个
    gfolderpath
    变量。

    我猜您有两个函数或方法(或每个函数或方法中的一个)都包含这一行:

    static NSMutableArray *gFolderPaths = nil;
    
    那不行。两个
    gFolderPaths
    变量都是静态的,但也是您在其中声明它们的函数/方法的局部变量。每个函数/方法都有自己的
    gFolderPaths
    变量,因此有两个这样的变量,彼此独立

    您需要在任何函数或方法之外,将
    gFolderPaths
    声明为静态全局变量。更好的是,如果只从实例访问它,则将其设置为实例变量。无论哪种方式,如果要在两个函数或方法之间共享它,它都不能是局部变量


    另一种可能发生这种情况的方式是,如果您有两个这样的全局声明,但每个声明位于不同的文件中<在文件范围内声明的变量上的code>static表示“仅在此文件中可见”,因此这会导致相同的问题:当您想要有一个共享变量时,会出现两个单独的变量。如果这是您的问题,立即解决的办法是从这两个变量中删除
    static
    关键字,但是如果您打算以这种方式使用全局变量,您应该重新考虑您的设计。

    …这只是全局变量不好的一个原因。非常感谢Peter。你的回答很准确#3:我实际上已经声明了两个“gFolderPaths”,因为我会复制粘贴作业。e、 g.“NSMutableArray*GFolderPath=”中。哎哟已经做了20多年了,但我仍然被基本的东西咬着了。@亚历克斯,我很少用globals。我把它们和's'一起使用
    static NSMutableArray *gFolderPaths = nil;