Mac OS X 10.6,Cocoa项目,带保留/释放gc
我有一个功能:
e.g。 (为简洁起见,删除了错误处理)。
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;
}
调用函数每个会话只接受一次数组,保留它以供以后处理:
static NSMutableArray *gFolderPaths = nil;
...
gFolderPaths = ListAllSubFoldersForFolderPath(myPath);
[gFolderPaths retain];
在这个阶段,所有人都表现得很好。 [gFolderPaths count ]返回找到的正确路径数,[ gFolderPaths description] 打印出所有正确的路径名。
问题:
当我稍后使用 gFolderPaths 时(比如,下一次运行我的事件循环),我的断言代码(以及Xcode中的gdb)告诉我它是零。
我没有在初始抓取之后以任何方式修改 gFolderPaths ,所以我假设我的内存管理被搞砸了并且运行时正在发布gFolderPaths。
我的假设/推定
我没有保留每个字符串,因为我将它添加到可变数组中,因为这是自动完成的,但是我必须保留数组,一旦它从函数移交给我,因为我不会立即使用它。这是对的吗?
感谢任何帮助。
答案 0 :(得分:2)
对象不“去nil
”。
static NSMutableArray *gFolderPaths = nil;
此声明声明gFolderPaths
是一个包含指向NSMutableArray对象的指针的变量。
使用指向无对象的指针初始化它:nil
。
这个初始化是有效的,并且有意义,因为你没有一个数组可以放在这里 - 更好地使用nil
指针初始化而不是初始化并冒一些随机指针在变量中。 (static
变量不会发生这种情况,因为static
变量无论如何都被初始化为nil
,但显式性很好而且显式初始化是无害的。)
当我稍后使用
gFolderPaths
时(比如,下一次运行我的事件循环)我的断言代码(以及Xcode中的gdb)告诉我它是nil
。在初始抓取之后,我没有以任何方式修改
gFolderPaths
,因此我假设我的内存管理被搞砸了,并且运行时正在释放gFolderPaths
。
没有。运行时不释放对象。运行时是语言的一部分,retain
和release
是Foundation框架的一部分。该框架位于语言之上。
所以,你可能会猜到你或其他一些代码(例如,在框架中)发布了你之前存储在gFolderPaths
中的指针的对象。
没有。如果发生这种情况,gFolderPaths
变量不会突然包含nil
;它仍然包含指向同一对象的相同指针。如果这是对象死亡之前的最后一个版本,那么gFolderPaths
变量仍将包含指向相同的,现在已死的对象的相同指针。
尝试记录指针(例如,使用NSLog(@"%p", gFolderPaths)
)将打印一个看似有效的地址,例如0x2381ab6780
。尝试记录对象(例如,使用%@
)几乎肯定会崩溃,因为对象已经死了。
那不是发生了什么事。你说你的断言和你对调试器的命令显示gFolderPaths
变量包含nil
。
有两个明显的可能性:
nil
,或者您从未指定任何内容。你说你正在记录你指定给变量的指针的数组,并且说明检查了,所以我们可以完全忽略这种可能性。 (记录计数的测试不会那么可靠,因为[nil count]
将成功返回0。)这导致了第三种可能性:
3。 您有两个gFolderPaths
个变量。
我猜你有两个函数或方法(或其中一个)都包含这一行:
static NSMutableArray *gFolderPaths = nil;
那不行。两个gFolderPaths
变量都是静态的,但也是你声明它们的函数/方法的局部变量。每个函数/方法都有自己的gFolderPaths
变量,所以你有两个这样的变量,彼此分开。 / p>
您需要在任何函数或方法之外将gFolderPaths
声明为静态全局变量。更好的是,如果仅从实例访问它,则将其设为实例变量。无论哪种方式,如果您想在两个函数或方法之间共享它,它就不能是局部变量。
另一种可能发生的方式是,如果您有两个这样的全局声明,但每个声明都在不同的文件中。 static
在文件范围内声明的变量意味着“仅在此文件中可见”,因此这会导致同样的问题:当您想拥有一个共享变量时,需要两个单独的变量。如果这是您的问题,立即修复是从这两个关键字中删除static
关键字,但如果您打算以这种方式使用全局变量,则应重新考虑您的设计。