首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可可记忆管理-目标对我来说是零

可可记忆管理-目标对我来说是零
EN

Stack Overflow用户
提问于 2010-06-16 07:37:27
回答 1查看 104关注 0票数 0

MacOSX10.6,Cocoa项目,保留/发布gc

我有一个功能:

  • 遍历特定的目录,扫描它的子文件夹(包括嵌套的目录),构建字符串的NSMutableArray (每个找到的子文件夹路径一个字符串),并返回该数组。

例如(为简洁而删除的错误处理)。

代码语言:javascript
复制
NSMutableArray * ListAllSubFoldersForFolderPath(NSString *folderPath)
{
    NSMutableArray *a = [NSMutableArray arrayWithCapacity:100];
    NSString *itemName = nil;
    NSFileManager *fm = [NSFileManager defaultManager];
    NSDirectoryEnumerator *e = [fm enumeratorAtPath:folderPath];

    while (itemName = [e nextObject]) {
        NSString *fullPath = [folderPath stringByAppendingPathComponent:itemName];
        BOOL isDirectory;
        if ([fm fileExistsAtPath:fullPath isDirectory:&isDirectory]) {
            if (isDirectory is_eq YES) {
                [a addObject: fullPath];
            }
        }           
    }
    return a;
}

调用函数每个会话只接收数组一次,将其保存下来供以后处理:

代码语言:javascript
复制
static NSMutableArray *gFolderPaths = nil;

...

gFolderPaths = ListAllSubFoldersForFolderPath(myPath);
[gFolderPaths retain];

在这个阶段,一切看起来都很好。[gFolderPaths计数]返回找到的正确路径数,_gFolderPaths description_打印出所有正确的路径名。

问题:

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

在第一次抓取之后,我不会以任何方式修改gFolderPaths,所以我假设我的内存管理已经结束,gFolderPaths正在由运行时发布。

我的假设/假定

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

任何帮助都是非常感谢的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-06-16 10:12:59

对象不是“gonil”。

代码语言:javascript
复制
static NSMutableArray *gFolderPaths = nil;

此声明声明gFolderPaths是一个保存指向NSMutableArray对象的指针的变量。您可以使用指向no:nil的指针初始化它。

这个初始化是有效的,并且是有意义的,因为您还没有一个数组放在这里--最好用nil指针进行初始化,而不是不初始化并且冒着一些随机指针在变量中的风险。(这在static变量中是不可能发生的,因为static变量被初始化为nil,但是显式性很好,并且显式初始化是无害的。)

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

在第一次抓取之后,我不会以任何方式修改gFolderPaths,所以我假设我的内存管理已经结束,gFolderPaths正在由运行时发布。

不是的。运行时不释放对象。运行时是语言的一部分,retainrelease是基础框架的一部分。这个框架就在语言的顶端。

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

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

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

事情不是这样的。您说您的断言和调试器命令显示gFolderPaths变量包含nil

有两种明显的可能性:

  1. Something重新分配给变量.你说你的代码没有重新分配给变量.其他什么都不应该知道,所以这种可能性非常大,unlikely.
  2. You一开始就没有为对象分配指向变量的指针,不是指定了nil,就是没有分配任何东西。您说您正在记录您分配给变量的指针的数组,并且说明是正确的,所以我们可以完全排除这种可能性。(记录计数将不是那么可靠的测试,因为[nil count]将成功返回0.)

这导致了第三种可能性:

  1. You有两个 gFolderPaths variables.

我猜您有两个函数或方法(或每个函数或方法中的一个),它们都包含以下一行:

代码语言:javascript
复制
static NSMutableArray *gFolderPaths = nil;

那不管用。这两个gFolderPaths变量都是静态的,但也是声明它们的函数/方法的本地变量。每个函数/方法都有自己的gFolderPaths变量,因此您有两个这样的变量,彼此分离。

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

如果您有两个这样的全局声明,但每个声明位于不同的文件中,则可能发生另一种情况。在文件作用域中声明的变量的static意味着“仅在此文件中可见”,因此这会导致同样的问题:当您打算拥有一个共享变量时,两个单独的变量。如果这是您的问题,立即修复是从它们中删除static关键字,但是如果要以这种方式使用全局变量,则应该重新考虑您的设计。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3051426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档