0

I am using the following line of code...

NSString *clientFirstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);

The 'analyse' feature on Xcode is saying that this giving rise to a potential memory leak. I am not releasing clientFirstName at all as I have neither alloc or retain'd it.

However, I am conscious that ABRecordCopyValue may not be returning an object as say a command like [NSMutableArray arrayWithArray:someArray] would which might mean I am indeed creating a new object that I control and must release.

Keen to hear thoughts...

Ben Thompson
  • 4,743
  • 7
  • 35
  • 52

3 Answers3

3

Any sort of copy returns an object with a retainCount of 1, so you need to release it via CFRelease().

See the doc:

You are responsible for releasing this object.

Christian Schnorr
  • 10,768
  • 8
  • 48
  • 83
  • Yep - that's worked. Still don't fully understand CFRelease yet! – Ben Thompson Apr 15 '12 at 14:05
  • `CFRelease()` does the same as sending a `release`-message to an object. – Christian Schnorr Apr 15 '12 at 14:06
  • @Jenox: From just a quick observation, I don't think your answer is completely correct. I think it is incomplete. Nothing personal! – Parth Bhatt Apr 15 '12 at 14:34
  • Would you mind telling me what exactly you think is incomplete? – Christian Schnorr Apr 15 '12 at 14:43
  • @Jenox If I am not wrong, I think you should specify to check the object and if object is not `nil`, then it is better to execute functions on the object as there is no point executing `release` for a nil object. You should specify this especially as Ben Thompson looks to be a fairly new programmer in objective-C. Hope this is fine. :) – Parth Bhatt Apr 16 '12 at 08:28
  • But being able to send messages to `nil` objects is such a great feature in Objective-C! I think he should - as a new programmer - know of this awesome stuff... – Christian Schnorr Apr 16 '12 at 11:37
1

Refer to this link. It has same as yours:

NSString potential leak

Refer to answer of KennyTM:

ABMultiValueCopyValueAtIndex is a "Copy" function, which follows the "Create Rule". You need to call CFRelease to release it after finish using it.

NSString *contactEmail = (NSString *)ABMultiValueCopyValueAtIndex(emailInfo, 0);
...
if (contactEmail != nil)
  CFRelease((CFTypeRef) contactEmail);

Release your object clientFirstName using CFRelease.

Add the code below:

if(clientFirstName != nil)
{
     CFRelease((CFTypeRef) clientFirstName);
}

NOTE: Do not forget to check if clientFirstName is not nil. It is better to have a practice of checking that object is not nil before executing any function on it as it saves us from potential crashes though not in this case, but in many cases

Edit

Also as @Dondragmer says in one of the comments below:

I think even this should solve the problem:

[clientFirstName release];
halfer
  • 19,824
  • 17
  • 99
  • 186
Parth Bhatt
  • 19,381
  • 28
  • 133
  • 216
  • Since `NSString` is toll-free bridged with `CFStringRef`, it is sufficient to call `[contactEmail release]` instead of `CFRelease((CFTypeRef) contactEmail)`. Both statements will have the same effect, but the first is safer: it doesn't matter if you call the Objective-C `release` on a `nil` object. – Cowirrie Apr 15 '12 at 14:34
  • @Dondragmer: No Offense to you but I still prefer that it is better to have a practice of checking that object is not `nil` before executing any function on it as it saves us from potential crashes in some cases. Also I would prefer the second `CFRelease((CFTypeRef) contactEmail)`. – Parth Bhatt Apr 15 '12 at 14:38
  • @Dondragmer: Also would like to ask you why you feel `[contactEmail release];` is safer? I believe second one is the one that should be used. – Parth Bhatt Apr 15 '12 at 14:41
  • if the programmer makes a mistake and calls `[contactEmail release];` without checking for `nil`, it won't crash. Calling `CFRelease((CFTypeRef) contactEmail);` in the same circumstances will cause a crash. As long as memory isn't being corrupted, not crashing is safer than crashing. It is also possible to call `[contactEmail autorelease];` immediate after creating the string, putting allocation and deallocation at the same point in the program. – Cowirrie Apr 15 '12 at 22:22
  • @Dondragmer: Ok thanks for the information. I have edited my answer and added your point in EDIT section of answer. Thanks for the information :) – Parth Bhatt Apr 16 '12 at 05:25
0

I don't fully understand how ObjectiveC reference counting works, but a small update in code fixed the Analyze warning:

Before:

NSString *firstName = (__bridge NSString*) ABRecordCopyValue(person, kABPersonFirstNameProperty);

After

NSString *firstName = (__bridge_transfer NSString*) ABRecordCopyValue(person, kABPersonFirstNameProperty);
Roozbeh Zabihollahi
  • 7,207
  • 45
  • 39