What is the memory management problem with this bit of code? - ios

The XCode analyzer tells me there is a problem at line 4 — return [originalError copy]; — but I don't see it. Help me please?
- (NSError *)errorFromOriginalError:(NSError *)originalError error:(NSError *)secondError
{
if (secondError == nil) {
return [originalError copy];
}
// ...
}
The problem description is:
Potential leak of an object allocated on line 203
Method returns an Objective-C object with a +1 retain count (owning reference)
Object returned to caller as an owning reference (single retain count transferred to caller)
Object allocated on line 203 is returned from a method whose name ('errorFromOriginalError:error:') does not contain 'copy' or otherwise starts with 'new' or 'alloc'. This violates the naming convention rules given in the Memory Management Guide for Cocoa (object leaked)
Potential null dereference. According to coding standards in 'Creating and Returning NSError Objects' the parameter 'error' may be null
The third issue seems to suggest I should either change the name or the behaviour of the method further. Any suggestions on that? The method is derived from the errorFromOriginalError:error: method described in Apple's Core Data Validation document. Its purpose is to combine originalError and secondError so that secondError is a sub-error of originalError.
My addition tries to ensure that the method still works if there is no actual secondError. Since a new error object is created if secondError is not nil, I wanted to recreate that in the case displayed above by simply copying the error object.

You are making a copy of originalError, but your function name implies that the returned object will be autoreleased. Try
return [[originalError copy] autorelease];

[originalError copy] creates a new object with a retain count set to 1. It would then be the responsibility of the calling method to release that object. If you're doing this then it isn't necessarily a problem, but it's probably a better ideas to autorelease it.
ie
return [[originalError copy] autorelease];

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.

use __weak to local variable in ARC

When you write code like below in ARC
__weak NSMutableArray* array = [[NSMutableArray alloc] init];
The compiler will show you a warning or error and say "Assigning retained object to weak variable. object will be released after assignment".
But if you write like this:
__weak NSMutableArray* array = [NSMutableArray array];
There is no error.
I'm wondering if the second usage is reasonable in some situations? What's the difference between these two codes from memory management perspective? How does it work?
There can be very subtle differences that the compiler cannot know.
Let's take an immutable version: [NSArray array] could return the very same static object every time. So your weak variable will point to a valid object, that has a strong reference somewhere else. Or think of the singleton pattern. On the other hand, when calling alloc/init, convention dictates that you're the only owner of that object, and that will typically leave you with nothing.
Also, the factory method certainly looks more like a (functional) method. In any case, it doesn't communicate ownership of what it returns very well. For an autoreleased object, it's not clear whether you're the the only owner or a shared owner.
They are the same because you lose the object instantly. Compiler cannot know probably, except alloc init, that the object will be lost.
In the first form, the method returns a retained object. ARC ensures, that the object is released when there is no strong reference on the call-site. This is immediately true, with the weak reference - thus, the compiler emits a warning or error.
In the second form, the method returns an unretained object. In this case, the compiler must ensure that the object is still valid across the return boundary. When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain while ensuring that the value lives across the call boundary. That is, there is a strong reference created by the compiler. This strong reference will be automatically released by the compiler generated code.
Thus, in this case there's no error or warning.
In the worst case, holding that object may require to use an autorelease pool. However the compiler can apply certain optimisations which avoids this. Thus we should not assume that the returned object lives in an auto release pool.
See specification: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id14
See also this question on SO: Difference between [NSMutableArray array] vs [[NSMutableArray alloc] init]

CFBridgingRelease ussage when assigning to a property - is niling it out necessary ("Crossing the Bridge")

I am using a CFBridgingRelease when acquiring a network stream:
self.networkStream = CFBridgingRelease(
CFReadStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) url)
);
The property definition is:
#property (strong, readwrite) NSInputStream *networkStream;
In certain circumstances (when a proper streamEvent is received in the run loop) I finish the operation:
if (self.networkStream != nil) {
[self.networkStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.networkStream close];
self.networkStream.delegate = nil;
self.networkStream = nil;
}
This is made as an NSOperation (adding to a NSRunLoop for a thread like AFNetworking one).
It is based on the Apple example:
https://developer.apple.com/library/ios/samplecode/SimpleFTPSample/Introduction/Intro.html
Should i make the
self.networkStream = nil
or will it be managed by ARC and the nil is unnecessary or even bad?
Also when I use the CFBridgingRelease is the Release made on acquire or when niling the value or how does it exactly work (I've done some reading and I k'now it is "passing the memory management responsibility to ARC" for an object acquired from CoreFoundation using "Create/Copy" as the "Create Rule"). Perhaps some more insight or info on it?
Thx in advance.
EDIT:
Ok.. Went through your comments but I have one issue mentioned
NSStream error in specific configuraion
In a nutshell => It works ok (even when trying to download an non existent file) but when the FTP server has bad rights it crashes and only in RELEASE configuration. I added two pictures from instruments -> one when I do nil out the property and the other when I don't.
Again - this only happens in RELEASE and in that specific FTP configuration!
This is tightly related so please if you have any ideas anwser on that thread.
This line
self.networkStream = nil
is not necessary, but it's not bad either.
ARC releases a resource when it's no longer needed, in other words, when there are no strong references to it, this means that the resource is released when you set it to nil, or when the variable referencing it goes out of scope (this should answer both your first and second questions).
In your case, since this variable is a member of your class, if you set it to nil it will be released immediately (to be precise, at the end of the current run loop). If you don't set it to nil, it will be released when your class is destroyed.
CFBridgingRelease does just what you say it does, your insight is fine. If you have an owned CF object which is one of the toll-free bridged types then you can transfer your ownership to ARC to manage. Despite the name, CFBridgingRelease doesn't "release" the object in the retain-release sense, it releases you from having to manage the ownership.
When it is no longer required ARC will relinquish your ownership of the object automatically, and if there is no other ownership interest that will result in the object being freed (released).
Assigning nil to a variable/property of strong reference type cannot be "bad" in the sense it could break memory management. Such an assignment simply relinquishes an ownership interest in the referenced object. Assigning nil is often unnecessary as ARC will relinquish ownership in a timely fashion; but, for example, if you have a property on a long-lived object you may want to assign nil to the property to relinquish your interest sooner.
Of course assigning nil can be "bad" in a program-logic sense if you actually need the object and the assignment causes it to be released!
HTH
No need to set property to nil value. ARC will take care releasing that object.
CFBridgingRelease : It will transfer ownership to ARC, if passed object is Owned by you.(__bridge_transfer use this, while you are casting object)
CFBridgingRetain : It will transfer ownership to you from ARC(__bridge_retained).
If you don't want to transfer ownership, then you need to cast one objet to another object using "__bridge".
All object owned by you should be released after its Usage. It may be you received ownership by using CFBridgingRetain(), you should release that object.

Releasing Singletons

I was wondering how you would release a singleton
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
// Not autoreleased, as it is basically a singleton:
return [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
}
When analysing this using the analyse tool i get the following error :
Potential leak of object on line 90. which is the line that returns.
I have tried autorelease that solves the error message problem but im not convinced its the right solution since i read that autoreleasing singletons is not good. Would someone be able to assist me in identifying how best to release this object?
Thanks
The reason why the analyzer gives you the warning is, basically, the method name:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
according to Objective-C conventions, all method names starting with "create"/"new"/... return a retained object; your method falls under the category of convenience constructors, which are expected to return autoreleased objects, hence the warning.
On the other hand, you say this is a singleton, but in fact it is not. So, you could possibly end up calling this method more than once and thus have an actual leak. A basic way to make your method safer (and more singleton-like) is:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
static DSActivityView* gDSActivityViewSingleton = nil;
if (!gDSActivityViewSingleton)
gDSActivityViewSingleton = [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
return gDSActivityViewSingleton;
}
This would both make the analyzer relax and give you more safety in front of the possibility of misuse of the method.
Use autorelease. There's no reason not to. Basically ownership of the object belongs to the object, so you're never going to be able to manually release it. As its a singleton it doesn't matter if you don't own it because presumably next time you call it and need it in scope you'll use another convenience method and it will get instantiated again.
If you want to have ownership of the object then you will need to instantiate it as normal and then you will be able to retain and release it.
Also, read sergio's edit about it not being a "proper" singleton. :p
Also, if you can, convert to ARC and you won't have to worry about this!
U are doing it wrong. Consider:
If you calling activityViewForView multiple times, you won't get get the same object over and over again. It only would initialize a new object and give you the pointer to it!!!
To make this thing a singleton, you have to store the created object in a constant variable and make sure, you have a reference to this object all the time your app is running (for instance declare your pointer to this object in appDelegate).
Then every time you call activityViewForView you have to check the constant variable if it is pointing to a valid object. If so, return the valid object, if not, create it and store it in your constant static variable (creation is done only once).
If you do use ARC you're all set. If not, release your object (use dealloc method)

When to make object nil and when to call release

Today I see code in which user is releasing the object first and then he is making that object nil. like this
[objectA release];
objectA=nil;
I have read at many books that we should make the object nil while leaving the view and release the object later(in dealloc method of course this method is called after viewWillDisappear or viewDidDisappear).
Now i want to know that which approach is better?
Setting to nil and releasing are two distinct operations.
You release an object to relinquish ownership of it. This is covered in the standard Memory Managemange Guidelines. If you are not familiar with them, you should read them before doing any further iOS programming.
After releasing an object, you should set it to nil if you know that some other code may attempt to access that variable later. This is most common with instance variables.
For example, you may use an instance variable to store some sort of cache:
- (NSArray *)items
{
if (!cachedItems) {
cachedItems = [[self calculateItems] retain];
}
return cachedItems;
}
Later on you may need to clear this cache:
- (void)invalidateCache
{
[cachedItems release];
cachedItems = nil;
}
We need to set cachedItems to nil because our items method may attempt to use it later. If we do not set it to nil, messages send to the (now released) cache can lead to a crash.
So set a variable to nil after releasing it when it can potentially be access by other methods in your class at a later point in time.
I don't think is important set object to nil, but is good to do.
If you do :
objectA = nil;
[objectA release];
You have LOST the memory, and this is a memory leak. If you only do [objectA release], you will release the memory, but the objectA still point to the memory, so if you try to do things like:
if (objectA==nil)
This will return FALSE, because objectA is NOT a nil. But because you do this almost in
- (void)dealloc;
you don't need set it to nil in this function.
If the object is created locally:
I would go with the first approach, it's a common practice to release the object first then assign an nil.
I haven'nt read about your second approach in any book.
If the object is the part of class variable and have retain and #synthesize :
The below will do the both work (first release then assign nil through setter function) at once.
self.object = nil ;
First approach is the way to go for you..
[objectA release];
objectA=nil;
Also making object nil is a good practice (not if you are using it later) because after releasing the object, if I accidentally refers to it again your app will crash. But if you gave nil to the object, and you refer to it later it won't crash in objective C.(Situations similiar gave nullpointerException in languages like java)
ie
[objectA doneSomeTask];
wont crash,even if objectA is nil. As objective C silently ignores refering to nil.
What you have read in books does not work. If you set the object to nil you can not release it later because you can not excess the object then. You should to the first approach.
Best way:
[objectA release]; // sightly sightly faster since less function calls
objectA=nil;
Lazy way:
self.objectA=nil;
it will call:
(void)setObjectA:(ObjectAClass *)objectA
{
[objectA release]; // <-- original value is released
objectA = [objectA retain];// <-- set the point to nil and do nothing since nil
}

Resources