release CFString - iphone

I use this code to get the last name of ABPerson
CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
NSString *friendLastName = (NSString*)lastNameRef;
CFRelease(lastNameRef);
it work fine when the value of last name is not equal to NULL
but when the this value is NULL the application crash at the third line because I try to relese NULL
the question is witch is the best way to releasing the CFString in this case without causing the crash of the application

Just use an if to check for NULL.
if (lastNameRef != NULL)
CFRelease(lastNameRef);

CFRelease is old C style code. One should check for NULL before calling CFRelease as also set lastNameRef to NULL after calling CFRelease.
if (lastNameRef != NULL)
{
CFRelease(lastNameRef);
lastNameRef = NULL;
}

CFRelease expects a non-NULL pointer. You could check for that with an if statement, but it is easier to simply release or autorelease friendLastName instead:
CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
NSString *friendLastName = (NSString*)lastNameRef;
// use friendLastName
[friendLastName release];
or
CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
NSString *friendLastName = (NSString*)lastNameRef;
[friendLastName autorelease];
// use friendLastName
As you don't seem to use lastNameRef, you could also inline that variable:
NSString *friendLastName = (NSString*)ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
// use friendLastName
[friendLastName release];
or
NSString *friendLastName = (NSString*)ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
[friendLastName autorelease];
// use friendLastName

Related

Potential leak of an object stored into setting username and setting password value

I am analyzing my application and face Potential leak of an object stored into setting username and setting password value my code is given
-(void) checkRememberPassword{
CFStringRef userNameKey = CFSTR("user_id_preferences");
CFStringRef settingUserName = (CFStringRef)CFPreferencesCopyAppValue(userNameKey, kCFPreferencesCurrentApplication);
CFStringRef passwordKey = CFSTR("password_preferences");
CFStringRef settingPasswordValue = (CFStringRef)CFPreferencesCopyAppValue(passwordKey, kCFPreferencesCurrentApplication);
NSString *tempString = (__bridge NSString *)settingPasswordValue;
NSString *tempString1 = (__bridge NSString *)settingUserName;
if(([tempString1 length] != 0) || ([tempString length] !=0)){
txtUserName.text = (__bridge NSString *)settingUserName;
txtPassword.text = (__bridge NSString *)settingPasswordValue;
[checkBoxButton setImage:[UIImage imageNamed:#"checkbox_full.png"] forState:UIControlStateNormal];
flagForRemPassword = YES;
}
}
The string returned by CFPreferencesCopyAppValue follows the Create rule (https://developer.apple.com/library/ios/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-103029) in Core Foundation -- you need to call CFRelease when you are finished with it. ARC does not do this for you.
Use CFBridgingRelease to transfer ownership of the object to ARC, instead of a simple C-style cast:
NSString *tempString = (NSString*)CFBridgingRelease(settingPasswordValue);

peoplePickerNavigationController leaks

I'm trying to get name and last name from Contacts and store the values in a couple of NSString:
CFStringRef cfName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
self.stName = (NSString *)cfName;
CFRelease(cfName);
CFStringRef cfLastname = ABRecordCopyValue(person, kABPersonLastNameProperty);
self.stLastname = (NSString *)cfLastname;
CFRelease(cfLastname);
The problem is, if firstname or lastname are empty in contacts, when I release the CFStringRef the app crash with EXC_BAD_ACCESS (zombie?).
If I don't release the CFStringRef I have a leak.
Any suggestion is appreciated.
Max
Yes, CFRelease will crash (halt) if you pass it a NULL argument.
This was allready mentioned by sbooth here.
CFRelease looks like this:
void CFRelease(CFTypeRef cf) {
if (NULL == cf) HALT; //this line will get you
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if (CF_IS_COLLECTABLE(cf)) {
if (CFTYPE_IS_OBJC(cf)) {
// release the GC-visible reference.
auto_zone_release(auto_zone(), (void*)cf);
} else {
// special-case CF objects for better performance.
_CFRelease(cf);
}
return;
}
#endif
source
Therefor it's your responcibility to check if you're passing it a NULL or not.
You were correct in your (deleted) answer. Code should look like:
CFStringRef cfName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
self.stName = (NSString *)cfName;
if (self.stName) CFRelease(cfName);
CFStringRef cfLastname = ABRecordCopyValue(person, kABPersonLastNameProperty);
self.stLastname = (NSString *)cfLastname;
if (self.stLastname) CFRelease(cfLastname);
You still might get compiler warnings but this code should work fine.

Memory leak in iphone App when analyzed

I'm getting a memory leak signal like the one shown in
how can i clear this, please help me .
Use (__bridge_transfer NSString *) instead of (__bridge NSString *)
With ARC, you can use __bridge_transfer to transfer memory management of the returned string to ARC
Example:
NSString *myString = [self encodeURL:#"hi*)"];
NSLog(#"%#",myString);
-(NSString *)encodeURL:(NSString *)string{
NSString *newString = #"";
newString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR("^%*)*&%$"),CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
return newString;
}
Try this...
NSString *newString = nil;
CFStringRef stringRef = CFURLCreateStringByAddingPercentEscapes(...);
newString = (NSString *)stringRef;
CFRelease(stringRef);
if(newString)
return newString;
Use
return [newString autorelease];
The NSString object newString is got allocated in the function CFURLCreateStringByAddingPercentEscapes.
so the object attaining the retain count of one at this moment. So when you are retuning the retained object you got memory leak signal. We can add the object newString to the autorelease pool so that the os will take care of the memory to release at the right time.
Hope this helps.

Call to function 'CFUUIDCreate' returns a Core Foundation object with a +1 retain count

Added share kit group to the project and found so many compile warnings fixed most of them but few are still showing.
This one is from OAMutableURLRequest.m class
- (void)_generateNonce
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
NSMakeCollectable(theUUID);// **Reference count decremented on this line**
nonce = (NSString *)string; //**Incorrect decrement of the reference count of an object that is not owned at this point by the caller on this line**
}
Have no idea how to fix this one.
Thanks for help.
Solved it. Actually i was not share that what to release in this case but when i added
- (void)_generateNonce
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
NSMakeCollectable(theUUID);
nonce = (NSString *)string;
//[string autorelease];
CFRelease (theUUID);
}
It worked. Looks like i was responsible to release the theUUID which i allocated in CFUUIDCreate.

variable parameter function - EXC_BAD_ACCESS when calling [obj release];

I have the following method:
(void)makeString:(NSString *)str1,... {
va_list strings;
NSString *innerText = [[NSString alloc] init];
NSString *tmpStr = [[NSString alloc] init];
if (str1) {
va_start(strings, str1);
while (tmpStr = va_arg(strings, id)) {
innerText = [innerText stringByAppendingString:tmpStr];
}
label.text = [str1 stringByAppendingString:innerText];
}
[tmpStr release];
}
I will eventually get to Objective C Memory Management reading, where I'm sure I will find the answer to this - probably related to pointers and copying - , but for now, can anyone explain why if I add [innerText release]; as the last line of this function, i get an EXC_BAD_ACCESS error at runtime?
First, your code is erroneous.
As far as I can see you are only concatenating the strings to assign the result to label.text.
I assume that label is an ivar, so label.text = … ist legal. Then the following should do it:
- (void)makeString: (NSString *)str1, ...
{
if (str1) {
NSString *tmpStr;
va_list strings;
va_start(strings, str1);
while (tmpStr = va_arg(strings, id)) {
str1 = [str1 stringByAppendingString: tmpStr];
}
label.text = str1;
}
}
Some notes:
You should not release any input parameter unless your method is about releasing something.
As the first answer stated, you should not release the result of stringByAppendingString: unless
you have retained it before.
[Update]
I changed the answer because it contained an error. label.text = str1 should retain str1 of course (if it wants to keep it). Especially the calling code should not retain str1 unless it wants to keep it for itself.
stringByAppendingString returns an autoreleased string, which is replacing your original assignment. So your release is not needed. But you are leaking memory with the two allocs above.
You should probably use [NSString initWithCString:va_arg(strings, id)] to assign the tmpStr too.