IOS/xcode/Core Foundation: If a value is null do you have to release it? - core-foundation

my app has been crashing on releasing values pulled from an address book that turned out to be null
Is it okay to only release if the value is not null or do you always have to release?
CFStringRef firstName = ABRecordCopyValue(lRef,kABPersonFirstNameProperty);
// CFRelease(firstName);// this was causing crash
if(firstName!=NULL) {
CFRelease(firstName);
}
Newb to core foundation so appreciate guidance.

If the argument is NULL, CFRelease will cause a runtime error and your application will crash.
If the retain count of CFTypeRef objects becomes zero the memory allocated to the object is deallocated and the object is destroyed. If you create, copy, or explicitly retain (see the CFRetain function) a Core Foundation object, you are responsible for releasing it when you no longer need it.
so yes, you should only call CFRelease if firstName is not NULL when you no longer need it.

Related

NSProxy forwardInvocation: Return an new NSProxy instance cause memory leak

I try to use NSProxy to wrap object and make an proxy instance in (forwardInvocation:) as invocation' retValue, but all proxyon instance from can't be release in ARC. I've been troubled for a long time.
demo at github:https://github.com/JorrisRaghan/proxyon
you can see console log:
DEALLOC PPObject:...
DEALLOC Proxyon:Class< PPObject >
but without DEALLOC Proxyon:id< PPObject >".
you also can use Instruments to check memory leak.
so I need your help to solve it, thank you!
Update:
I found that this leak is from forwardInvocation:
void *proxyon = (__bridge_retained void *)[Proxyon proxyonWithInstance:obj];
[anInvocation setReturnValue:&proxyon];
I set PPObject as retVal instead of Proxyon instance, and leak happened in PPObject, so I guess -[NSInvocation setReturnValue:] is the key.But how to solve it?
The __bridge_retained cast looks wrong. __bridge_retained gives you a retained reference. You then set this as the return value of the invocation, without a balancing release, so the effect is that the call is returning a retained reference. But the name of the method that this is for (instanceWithIdentifier:) does not begin with alloc, new, retain, copy, or mutableCopy, and so should not return a retained reference.
Changing it to a simple __bridge cast should make it balanced again.

Is there any leak in NSAutoreleasepool?

What will be result ? is there any leak or crash??
-(NSString)returnPersonName {
NSAutorelease *pool = [[NSAutorelease alloc]init];
NSString *name = [[[NSString alloc]initWithString:#"Name"]autorelease];
[pool drain];
return name
}
bit confusing to me.
This code violates memory management rules. You do alloc, so you get ownership of a +1 reference count, and then you do autorelease on it, by which you give up your ownership of the reference count. Therefore, you should not use name anymore, and it is not guaranteed to point to a valid object. You return it, a pointer to a potentially invalid object.
In this particular case, because of the implementation details of Cocoa, nothing "bad" will happen. The body of that function is equivalent to just return #"Name";. #"Name" is a string literal, and string literals are stored in static storage that exists for the entire lifetime of the program. That means those string objects are not subject to memory management -- retain, release on them have no effect. You do [[NSString alloc] init...] on it, but NSString's initializers are optimized to simply retain and return its argument if the argument is already an immutable string. So you are not returning a new NSString object; you are just returning the same string literal which is statically allocated and not subject to memory management. Again, all this is implementation details of Cocoa that you cannot rely on.
I'm tipping the above could potentially crash because [pool drain] will cause name to be deallocated before it can be returned.
In a reference-counted environment, the drain method behaves the same as release. Since an autorelease pool cannot be retained, this therefore causes the receiver to be deallocated. When an autorelease pool is deallocated, it sends a release message to all its autoreleased objects. If an object is added several times to the same pool, when the pool is deallocated it receives a release message for each time it was added.
The pool is not required, for something like this try -
-(NSString*)returnPersonName {
NSString *name = [[[NSString alloc]initWithString:#"Name"]autorelease];
return name;
}
More info can be found in the Advanced Memory Management Programming Guide
On a side note - an #autorelease { } pool block is better to use than NSAutoreleasePool and even better is switch to ARC!

Can Core Foundation be used in PLCrashReporter signal callback?

I'm using PLCrashReporter in my iOS project and I'm curious, is it possible to use Core Foundation code in my custom crash callback. The thing, that handle my needs is CFPreferences.Here is part of code, that I create:
void LMCrashCallback(siginfo_t* info, ucontext_t* uap, void* context) {
CFStringRef networkStatusOnCrash;
networkStatusOnCrash = (CFStringRef)CFPreferencesCopyAppValue(networkStatusKey, kCFPreferencesCurrentApplication);
CFStringRef additionalInfo = CFStringCreateWithFormat(
NULL, NULL, CFSTR( "Additional Crash Properties:[Internet: %#]", networkStatusOnCrash);
CFPreferencesSetAppValue(additionalInfoKey, additionalInfo,
kCFPreferencesCurrentApplication);
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
}
My target is to collect some system information, just in time when app crashed, e.g Internet connection type.
I know it is not good idea to create own crash callback due to async-safe functions, but this can help.
Also as other option: Is there a way to extend somehow PLCrashReportSystemInfo class?
This is very dangerous. In particular the call to CFStringCreateWithFormat allocates memory. Allocating memory in the middle of a crash handler can lead to battery-draining deadlock (yep; had that bug…) For example, if you were in the middle of free() (which is not an uncommon place to crash), you may already be holding a spinlock on the heap. When you call malloc to get some memory, you may spinlock the heap again and deadlock in a tight-loop. The heap needs to be locked so often and for such short periods of time that it doesn't use a blocking lock. It does the equivalent of while (locked) {}.
You seem to just be reading a preference and copying it to another preference. There's no reason to do that inside a crash handler. Just check hasPendingCrashReport during startup (which I assume you're doing already), and read the key then. It's not clear what networkStatusKey is, but it should still be there when you start up again.
If for any reason it's modified very early (before you call hasPendingCrashReport), you can grab it in main() before launching the app. Or you can grab it in a +load method, which is called even earlier.

Objective C: Autoreleased objects between threads?

If I have an autoreleased object and I need to provide it to a different thread, what is the best way to do so?
Let's say I have an object that is autoreleased in thread 0. I tell thread 1 about this object and it retains it because it needs it. Later then it's done, it releases it. No problem. When thread 0 runs again and empties its autorelease pool, it sees the retain count is 1 and because it's an autoreleased object it deallocs. Everything is fine, therefore threads don't matter. Right?
By the way this was originally an interview question. The interviewer insisted that an autoreleased object cannot be given to another thread. He seemed almost angry about it. More and more in tech interviews, I encounter ppl who believe they know everything.
You should not pass autoreleased object directly to other thread.
in this code
id _sharedVariable; // ivar
NSConditionLock *_lock;
- (void)thread1
{
id objectNeedToPass = [[NSObject new] autorelease];
[_lock lock];
_sharedVariable = objectNeedToPass;
[_lock unlockWithCondition:1];
}
- (void)thread2
{
while (true)
{
[_lock lockWithCondition:1];
id objectReceived = [_sharedVariable retain];
[_lock unlockWithCondition:0]
process(objectReceived );
[objectReceived release];
}
}
thread2 may see _sharedVariable hold a released object (and crash)
because it may do this
thread 1 create and autorelease object
thread 1 assign it to the shared variable
thread 1 release the object
object deallocated
thread 2 read the object
thread 2 retain the object - crash
to solve the problem, you should pass a retained object
id _sharedVariable; // ivar
NSConditionLock *_lock;
- (void)thread1
{
id objectNeedToPass = [[NSObject new] autorelease];
[_lock lock];
_sharedVariable = [objectNeedToPass retain];
[_lock unlockWithCondition:1];
}
- (void)thread2
{
while (true)
{
[_lock lockWithCondition:1];
id objectReceived = _sharedVariable;
[_lock unlockWithCondition:0]
process(objectReceived );
[objectReceived release];
}
}
however, this may cause memory leak if second thread failed to release the object and make code hard to maintain (retain/release are hard to balance)
There is nothing to worry about at all as long as you are following the normal Cocoa memory management rules. Every single way of "providing it to a different thread" will work fine as long as you are following the rules.
Pretty much any time you "provide something to a different thread", it is asynchronous (unless you are using locks to do synchronous cross-thread execution or something). Which means that the other thread may (and will likely) use it after the current function on this thread has gone out of scope. Any time you store an object that needs to outlive the current execution, it needs to be retained. If you are storing it in an instance variable or global variable directly, then you are responsible for retaining it, according to the memory management rules. If you are storing it in some kind of container object, then that object is responsible for retaining it. So pretty much if you follow the rules, there is nothing to worry about.
Let's consider a common way that people execute things on another thread, with -performSelector:onThread:withObject:waitUntilDone:. If waitUntilDone is false, this function stores the receiver, selector, and argument in some kind of object to wait until the other thread is ready to execute it. Therefore, this function must be responsible for retaining the receiver and object when it places it into this structure, and releasing it when the structure is destroyed. And indeed it does -- if you read the pre-ARC documentation for the method, it says "This method retains the receiver and the arg parameter until after the selector is performed."
So basically the memory management rules are sufficient -- if you store the object in an instance variable, you need to retain it. If you pass it to some other function, then it's their job to take care of it.
Don't. Pass an owning reference to the other thread. The other thread will take ownership of the object and release it when done with it.
With autoreleased objects, you can't tell when the sending threads autorelease pool will be drained, and can't be sure if it will be drained before the receiving thread gets it.

Why this doesn't crash? [duplicate]

This question already has answers here:
Objective-C autorelease pool not releasing object
(2 answers)
Why can I send messages to a deallocated instance of NSArray?
(2 answers)
Closed 9 years ago.
Why the second line in the loop (the a.retainCount one) won't crash (due to bad access) ?
NSArray* a0 = #[[NSMutableString stringWithString:#"a"]];
NSArray * arr = [NSArray arrayWithObject:a0];
[a0 release];[a0 release];
for (NSArray* a in arr)
{
//NSLog(#"%d", (a == a0) );
NSLog(#"RC: %d", a.retainCount);
}
but it would crash if the first line in loop (a == a0 one) is un-commented.
This would definitely crash when the autorelease pool is drained, but I am specifically asking about the second line in loop, not afterwards.
Can anyone please explain?
Please review http://www.whentouseretaincount.com/
Sending a message to a deallocated object is undefined behavior. It may crash, it may not.
In this case, it isn't crashing because the memory that contained the object hasn't been overwritten by something else. If you were to turn on Malloc Scribble, it'd crash. That call to NSLog() coincidentally causes the memory to be scribbled upon, causing the crash.
retainCount can never return 0 exactly because messaging a deallocated object is undefined behavior. The system doesn't bother decrementing the RC to 0 because the object is no longer viable anyway.
I'm curious within what context this question came up? Are you using a tutorial or class materials that use retainCount?
It isn't always a segmentation fault for the same reason the runtime doesn't decrement the retain count to 0; efficiency.
To make it a guaranteed segmentation fault would mean wasting a few cycles writing bogus values to the memory (or decrementing the retain count).
As it is, free() just marks the memory as being available for future malloc()s. It doesn't modify the contents of the memory in any way, hence the undefined behavior.
This could crash any time. Likely the first line in the loop triggered the memory at the dangling pointer "a" allocated for other use. So when "a" is referenced on the second line, anything could happen.
If you turn on the XCode options in "Scheme -> Diagnostics -> Memory Management", this may crash immediately.

Resources