Reputation: 441
Doing code analysis of the project and get the message "Reference-counted object is used after it is released" on the line [defaults setObject: deviceUuid forKey: @ "deviceUuid"];
I watched this topic Obj-C, Reference-counted object is used after it is released? But the solution is not found. ARC disabled.
// 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"];
}
}
Please help find the cause.
Upvotes: 1
Views: 1795
Reputation: 44856
The problems is here:
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
deviceUuid = (NSString *)cfUuid;
CFRelease(cfUuid);
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
Let's go through what this actually does:
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
A CFUUID is created (and leaked). A CFStringRef is created and assigned to cfUuid. (Note: The name cfUuid implies that cfUuid is a CFUUIDRef. Of course, it isn't; it's a CFStringRef.)
deviceUuid = (NSString *)cfUuid;
That same CFStringRef is type cast and assigned to deviceUuid. This is not a new instance of NSString or CFStringRef, it's just a typecast of the same instance.
CFRelease(cfUuid);
You release the CFStringRef. Since the NSString points to the same object, you also release it.
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
And here, you use the typecasted object, which was released before.
THe simplest fix to the stale pointer is this:
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
deviceUuid = (NSString *)cfUuid;
[defaults setObject:deviceUuid forKey:@"deviceUuid"];
CFRelease(cfUuid);
But this code is dangerous, and you already know why: deviceUuid is also invalid. But this isn't obvious, so you can trip on it later. Also, it doesn't fix the CFUUID leak.
To fix the CFStringRef leak, you could use this:
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
However, this still doesn't fix the CFUUID leak.
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
Upvotes: 5
Reputation: 55533
The problem is Here:
CFRelease(cfUuid);
You shouldn't release that, you should release deviceUuid
when you are done with that.
Upvotes: 1