End*_*vet 1 iphone memory-leaks objective-c ios
对项目进行代码分析,在[defaults setObject: deviceUuid forKey: @“deviceUuid”]行上得到“ Reference-counted object is used after it release”的提示;
我看了这个话题 Obj-C,Reference-counted object 释放后使用? 但是没有找到解决办法。ARC 禁用。
// Get the users Device Model, Display Name, Unique ID, Token & Version Number
UIDevice *dev = [UIDevice currentDevice];
NSString *deviceUuid;
if ([dev respondsToSelector:@selector(uniqueIdentifier)])
deviceUuid = dev.uniqueIdentifier;
else {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id uuid = [defaults objectForKey:@"deviceUuid"];
if (uuid)
deviceUuid = (NSString *)uuid;
else {
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
deviceUuid = (NSString *)cfUuid;
CFRelease(cfUuid);
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
}
}
Run Code Online (Sandbox Code Playgroud)
请帮忙找出原因。
问题在这里:
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
deviceUuid = (NSString *)cfUuid;
CFRelease(cfUuid);
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
Run Code Online (Sandbox Code Playgroud)
让我们来看看它的实际作用:
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
Run Code Online (Sandbox Code Playgroud)
创建(并泄露)一个 CFUUID。CFStringRef 被创建并分配给 cfUuid。(注意:名称 cfUuid 暗示 cfUuid 是一个 CFUUIDRef。当然,它不是;它是一个 CFStringRef。)
deviceUuid = (NSString *)cfUuid;
Run Code Online (Sandbox Code Playgroud)
相同的 CFStringRef 是类型转换并分配给 deviceUuid。这不是NSString 或 CFStringRef 的新实例,它只是同一实例的类型转换。
CFRelease(cfUuid);
Run Code Online (Sandbox Code Playgroud)
您释放 CFStringRef。由于 NSString 指向同一个对象,因此您也将其释放。
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
Run Code Online (Sandbox Code Playgroud)
在这里,您使用之前发布的类型转换对象。
对陈旧指针的最简单修复是这样的:
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
deviceUuid = (NSString *)cfUuid;
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
CFRelease(cfUuid);
Run Code Online (Sandbox Code Playgroud)
但是这段代码很危险,你已经知道为什么了:deviceUuid 也是无效的。但这并不明显,因此您可以稍后再使用它。此外,它不能修复 CFUUID 泄漏。
要修复 CFStringRef 泄漏,您可以使用:
deviceUuid = (NSString *)CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
[deviceUuid autorelease]; // or release, if you don't need it in code not
// included in your post
Run Code Online (Sandbox Code Playgroud)
但是,这仍然不能修复 CFUUID 泄漏。
CFUUIDRef cfuuid = CFUUIDCreate(NULL);
deviceUuid = (NSString *)CFUUIDCreateString(NULL, cfuuid);
CFRelease(cfuuid);
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
[deviceUuid autorelease]; // or release, if you don't need it in code not
// included in your post
Run Code Online (Sandbox Code Playgroud)