Clarification of Autorelease Usage - ios

In most of the code that I've sen using autorelease, the object is ultimately returned from the function.Clearly release cannot be called after this point and autorelease is the way to go. However in situations where the object is going to passed to another object that will retain it is using autorelease just as valid?
For example
-(void)foo
{
SomeClass *someObject = [[[SomeClass alloc] init] autorelease];
//Do some things
self.someOtherClass.someProperty = someObject;
}
Is there any practical difference to releasing the object after it is assigned to someProperty:
-(void)foo
{
SomeClass *someObject = [[SomeClass alloc] init]];
//Do some things
self.someOtherClass.someProperty = someObject;
[someObject release];
}
Are there any situations where the later is more preferable to the former?

Both are acceptable, but you are accouraged to use the release version to avoid memory spikes an other problems.
It's acceptable to release here because you can assume that the receiver of the object will retain it, if it needs if later. So you can safely release as soon as it's given.

I think the latter will always perform slightly better in terms of memory usage and CPU usage, but only by a tiny amount per allocation.
Feel free to use the former if you prefer not to write three lines of code and are not having a performance problem. Note that the former can actually be written in one statement without a local variable at all.

Related

Can an object be deallocated during method execution?

Let's assume that we create an instance of class var foo: Foo? = Foo() on the main thread and we call some time consuming instance method bar of Foo on another thread, after a short time we set foo to nil on main thread. What happens with the execution of bar, in my understanding bar should still continue its execution since invoking instance method implicitly passes self as the first argument, so even those the last explicit ref to foo was broken we still have a ref inside of a method and it should be good. But then I found this stackoverflow post which completely breaks my understanding. So, can somebody confirm/deny the fact that object cannot be deallocated during its method execution
Short answer is that your belief is correct, and you're looking at a question that's not relevant to Swift.
Your link is to non-ARC Objective-C. Swift always uses ARC, and ARC is very conservative about retains. Consider the following Objective-C call:
[target runMethod: parameter];
Under ARC, this is (conceptually) transformed into:
[target retain];
[parameter retain];
[target runMethod: parameter];
[parameter release];
[target release];
retain and release are atomic, thread-safe calls.
A similar behavior exists in Swift. Because of this, as a general rule (in the absence of Unsafe), a variable cannot "disappear" while you'll holding onto it.
This is the implementation detail. The better way to think about it is that by default variables and parameters are strong, and an object cannot be destroyed while there is a strong reference. This matches your understanding.
Prior to ARC, though, you needed to insert extra retains and releases yourself to protect against this kind of situation, and it was very common not to. (Prior to 10.6, most ObjC was single-threaded.)
Even without threads, there are ways this can go astray without ARC. Since callers often didn't immediately retain returned values if they only needed them temporarily, it was possible to get dangling pointers even without multiple threads. For example, with a trivial accessor with no memory management, this can crash:
NSString *name = [person name];
[person release];
[self doSomethingWithName: name];
This is why you often see old ObjC getters written in the form:
- (NSString*) title {
return [[title retain] autorelease];
}
This made sure that the returned value would survive until the end of the event loop even if self released it or self was deallocated.
Swift does similar things via ARC, but as the name suggests, it's all automatic.

Why __weak variable not registered in autorelease pool?

id obj = [[NSObject alloc] init];
#autoreleasepool{
id __weak weakObj = obj;
_objc_autoreleasePoolPrint();
NSLog(#"%#",[weakObj class]);
_objc_autoreleasePoolPrint();
}
After running the code above, I get unexpected results when printing the pool:
objc[22671]: [0x7ff544817858] ################ POOL 0x7ff544817858
objc[22671]: ##############
I can't find the object registered in autoreleasepool. Why?
I think you've misunderstood what the autorelease pool is. It's a collection of objects that will receive a release messages to when the pool drains (most commonly at the end of an event loop). It's not a list of objects that will be "automatically released by some means." It's specifically the objects that will be sent a release message by this autorelease pool (and there may be multiple pools at any given time).
It has nothing at all to do with weak. "weak" is an attribute of a variable (pointer). "autoreleased" is something that has happened to an object. Objects may be autoreleased multiple times (and this is normal).
In manual memory management, this was done very commonly by sending -autorelease to the object. That means "don't release it now; I still need it, but when the current autorelease pool drains, release it." Note that this doesn't mean "destroy it." It just means "reduce the retain count by one." This is how you say "I only care about this object until the end of the event loop" (which is a very, very common thing to want to say).
In ARC you can't directly call -autorelease, but ARC still uses the autorelease pool in some cases. A very common way is by calling objc_autoreleaseReturnValue() on something before returning it. (This isn't something you call directly. It's something ARC injects automatically when needed.) In some cases, objc_autoreleaseReturnValue() still may not actually put the object on the autorelease pool. The compiler is smart enough to detect many cases where it can avoid the pool and improve performance. There are other cases where ARC may inject autorelease, and those cases also have optimizations where it may bypass the pool.
Note that there is generally no situation where this is something your app should rely on. _objc_autoreleasePoolPrint() is an Apple-internal function, and exists for low-level debugging. Whether something is in the autorelease pool or not is highly dependent on ARC implementation details and current compiler optimizations.
obj is never autoreleased, so it isn't placed in an autorelease pool. If you'd like obj to be autoreleased, you must call -autorelease on it, e.g.
#autoreleasepool {
id obj = [[[NSObject alloc] init] autorelease];
// ...
}
Note that -autorelease isn't available in ARC code.
I get the answer from this link .
The new implmenetation of __weak of Apple LLVM version 8.0.0 (clang-800.0.42.1) do not postpond the release to autoreleasepool, but use objc_release directly.

Thread-safe design with ARC

First of all let me quote a chapter from Apple Threading Programming Guide:
Be Aware of Threats to Code Correctness
When using locks and memory barriers, you should always give careful thought to their
placement in your code. Even locks that seem well placed can actually
lull you into a false sense of security. The following series of
examples attempt to illustrate this problem by pointing out the flaws
in seemingly innocuous code. The basic premise is that you have a
mutable array containing a set of immutable objects. Suppose you want
to invoke a method of the first object in the array. You might do so
using the following code:
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[arrayLock unlock];
[anObject doSomething];
Because the array is mutable, the lock around the array prevents other
threads from modifying the array until you get the desired object. And
because the object you retrieve is itself immutable, a lock is not
needed around the call to the doSomething method.
There is a problem with the preceding example, though. What happens if
you release the lock and another thread comes in and removes all
objects from the array before you have a chance to execute the
doSomething method? In an application without garbage collection, the
object your code is holding could be released, leaving anObject
pointing to an invalid memory address. To fix the problem, you might
decide to simply rearrange your existing code and release the lock
after your call to doSomething, as shown here:
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[anObject doSomething];
[arrayLock unlock];
By moving the doSomething call inside the lock, your code guarantees
that the object is still valid when the method is called.
Unfortunately, if the doSomething method takes a long time to execute,
this could cause your code to hold the lock for a long time, which
could create a performance bottleneck.
The problem with the code is not that the critical region was poorly
defined, but that the actual problem was not understood. The real
problem is a memory management issue that is triggered only by the
presence of other threads. Because it can be released by another
thread, a better solution would be to retain anObject before releasing
the lock. This solution addresses the real problem of the object being
released and does so without introducing a potential performance
penalty.
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[anObject retain];
[arrayLock unlock];
[anObject doSomething];
[anObject release];
And the question is: Is there any way to solve the problem while using ARC?
ARC solves this problem for you automatically; by default every pointer is a strong pointer, which means that the object is guaranteed to be retained until you are done using that pointer.
This means that whenever you get an object out of an array, ARC always retains that object. This guarantees its lifetime, even if the object is later removed from the array.

Guarantee a deallocation in ARC

I'm currently developing a game for iOS and we have a memory leak. Our project is ARC set up. I was wondering on how to ensure memory deallocation. One of the steps I was thinking of taking was convert code of the form:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
}
into:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
o = nil; // Explicit nil assignment
}
Is there a difference between the two? What other measures should I take to ensure a dealloc in an ARC setup?
We're using the Sparrow Framework.
Both methods do the same thing. Local objects are set to nil by ARC when they leave scope, so putting in a manual nil does nothing.
If you want to find a leak - you are far better off actually running it through Instruments with the Leaks tool and finding out what is being leaked, which will give you a better idea of what is going on. It's quite handy for finding retain-cycles.
As pointed out by Abizem, both methods lead to the same results, and require careful passes through Instruments. The results are not always easy to interpret.
In ARC, you should never see a leak - in the usual obj-C meaning -. Sometimes, iOS instruments can report a leak, but most if not all, this comes from the runtime, and I tend to regard them as beyond my control. What you can see however, is uncontrolled memory increase, which is typical of memory retention. Keeping strong pointers on objects is the obvious reason, which in my case has always been the consequence of : retain cycles in code blocks, and incorrect data structure cleanup, i.e. objects are created, then filled into arrays, dictionary, page control etc... but the later were not emptied properly during the app lifecycle.
Also image processing functions still use standard malloc/free directives embedded into internals UIGraphics lib, so in that case you explicitly need to free the memory (CGImageRelease, etc...). ARC will not help here.
hope this helps narrow down the problem, which as Abizem pointed out, should start with Instruments.
the following is unnecessary but (at least for me) the discussion in the comments was helpful and that's why I leave it
wrap the method in an #autoreleasepool. that will make it 99% percent sure it is being deallocated
-(void)methodMethod{
#autoreleasepool {
Object* o = [[Object alloc] init];
// Some logic
}
}
Both are the same.
A better solution to test your class:
- (void)testDealloc
{
__weak CLASS *weakReference;
#autoreleasepool {
CLASS *reference = [[CLASS alloc] init]; // or similar instance creator.
weakReference = reference;
// Test your magic here.
[...]
}
// At this point the everything is working fine, the weak reference must be nil.
XCTAssertNil(weakReference);
}
This works creating an instance to the class we want to deallocate inside #autorealase, that will be released (if we are not leaking) as soon as we exit the block. weakReference will hold the reference to the instance without retaining it, that will be set to nil.

Ambiguous scenario for iPhone memory management

I have some difficulties to understand this scenario.
I create an object
I set its retained property to something
I forget to release its property
I release the object
As I didn't release the property in the dealloc method, will the scenario result in a memory leak or will the property be released automatically?
The way Cocoa works is that memory management always looks locally balanced, within any one method*. This is kind of the point. You should be able to tell whether you have a leak or error in a method just by looking at that one method. No global program knowledge required.
It is your responsibility to release an object if you received the object from a -copy, -alloc, -retain, or -new method.
If you do this:
[obj setProp:foo];
is it your responsibility to release foo? No - see rules. If obj retains it (and you're saying you happen to know that it does), then it is the responsibility of obj to release it, in its dealloc method if not sooner.
So if you did this, it's balanced, no matter what kind of property -prop is.
id obj = [[MyObject alloc] init];
[obj setProp:foo];
[obj release];
*except for within the implementations of init, copy, dealloc, and accessor methods.
Yes, it's leak.
Retain, alloc will increase the counter by one.
Release will decrease the counter.
It will free the memory when the counter reaches zero.
Think of setter as this:
[newvalue retain];
[property release];
property = newvalue;
So..
create an object => 0+1=1
assign it to some object as a retain property => 1+1=2
release the object => 2-1=1
You will have to release that object again sometime.
And, trust me autorelease doesn't work quite well in the iphone environment.

Resources