I need to understand why in this code i get a memory leak if i assign value to ws_data variable using self.ws_data and not if i use only ws_data.
self.ws_data is a #property (copy)NSString *, released on dealloc.
dispatch_queue_t ws_queue = dispatch_queue_create("ws check win", NULL);
dispatch_async(ws_queue, ^{
self.ws_data = [[NSString alloc]initWithContentsOfURL:url];
});
dispatch_release(ws_queue);
Thank you!
self.variableName accesses the variable through its accessors. Because your ws_data NSString is set to copy in its property declaration, the string is retained when you set it through that declaration.
Not using self. references the ivar without going through those accessors. It also means the variable isn't copied, so it will vanish when references to it disappear (like at the end of your method).
Odds are you want the copy. You just need to release it when you're done, as you do in your dealloc.
Are you retaining it somewhere else, making this access a second retention?
If I understand things correctly (and I quite possibly don't as I've not be doing iOS development for very long at all) in this instance, as you're using the copy attribute on the property, what you're doing when you use self.ws_data is effectively calling the copy method on an already alloced NSString, which is creating a separate instance of the NSString with a retain count of one.
However, the original NSString (that's being alloced in your above sample) isn't being released at any point, hence the leak.
You could use...
self.ws_data = [[[NSString alloc]initWithContentsOfURL:url] autorelease];
...instead, I'd have thought.
Related
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.
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]
I am new to IOS development and I have started to learn objective c to program towards IOS 7. and as I know, it is way easier to code now than it has been before because of the Automatic reference counting.
there are a couple of things I do not understand . in MAIN method we have the autoreleasepool block, so my first question is that in order to enable ARC , the code has to be inside this block? if no, then what is the difference between the code that is inside autoreleasepool and the rest those aren't?
my second question is that when I am writing my IPHONE programs , I have bunch of classes and non of those codes are inside "autoreleasepool" , only the code inside the MAIN method.
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([HomepwnerAppDelegate class]));
}
}
so , does this mean that this block somehow magically gets applied to all lines of code inside any other classes of the same program?
My last question is that whether with ARC or without it, if we had a declared pointer variable inside a method, does the object gets released/destroyed when the method returns/exit?
assume we have a method like this :
- (void)doSomething {
NSMutableArray *allItems = [[NSMutableArray alloc] init];
NSString *myString = #"sample string";
[allItems addObject:myString]
}
then when we call this method and it exits, what would happen to those local variables defined inside the method ? is there any difference in the outcome if we are using ARC or not ? (Object are still in the memory or not)
Autorelease pools predate ARC by about 15 years. Cocoa uses a reference-counting memory management scheme, where (conceptually, at least) objects are created with a reference count of 1, retain increases it by 1 and release decreases the count by 1, and the object is destroyed when the count gets to 0.
A problem with this scheme is that it makes returning an object kind of awkward, because you can't release the object before you return it — if you did, it might be destroyed before the other method got to use it — but you don't want to require the other method to release the object either. This is where autorelease pools come in. An autorelease pool lets you hand an object to it, and it promises to release the object for you later. Under manual retain/release (the way we used to do things before ARC), you did this by sending autorelease to an object.
OK, so then ARC comes into the picture. The only thing that really changes with ARC is that you aren't the one writing retain, release and autorelease anymore — the compiler inserts them for you. But you still need an autorelease pool for autoreleased object to go into.
As for your second question:
My last question is that whether with ARC or without it, if we had a declared pointer variable inside a method, does the object gets released/destroyed when the method returns/exit?
assume we have a method like this :
- (void)doSomething {
NSMutableArray *allItems = [[NSMutableArray alloc] init];
NSString *myString = #"sample string";
[allItems addObject:myString]
}
then when we call this method and it exits, what would happen to those local variables defined inside the method ? is there any difference in the outcome if we are using ARC or not ?
If you're using ARC, the compiler will release any objects referenced by local variables. If you're not using ARC, you'd need write [allItems release] yourself, because the variable going out of scope does not magically cause the object it references to be released.
new to IOS development
Best not to worry, Automatic means that you mostly concentrate on other things ^)
does this mean that this block somehow magically gets applied to all lines of code inside any other classes of the same program
Yes. You're in main function, so all the code that is executed has to be inside this function - your app will terminate once it ends. Unless you create a separate thread, but it's hard to do that by accident.
the code has to be inside this block
As said above, all of your code on main thread will execute within this block.
what would happen to those local variables defined inside the method
You're guaranteed that they will be destroyed before returning.
in MAIN method we have the autoreleasepool block, so my first question is that in order to enable ARC, the code has to be inside this block? if no, then what is the difference between the code that is inside autoreleasepool and the rest those aren't?
ARC is enabled by corresponding Objective-C compiler setting. If you create a new project in the latest version of Xcode it will be enabled by default.
The #autorelease keyword places code inside the curly brackets into autorelease pool scope. Autorelease pools are used both with ARC and manual memory management.
my second question is that when I am writing my IPHONE programs , I have bunch of classes and non of those codes are inside "autoreleasepool" , only the code inside the MAIN method.
iOS applications are event based. Main thread starts event loop when you call UIApplicationMain function processing touch events, notifications etc. This event loop has its own autorelease pool that autoreleases objects at the end of the loop iteration. This autorelease pool has nothing to do with the autorelease pool you see in main function.
My last question is that whether with ARC or without it, if we had a declared pointer variable inside a method, does the object gets released/destroyed when the method returns/exit?
If you use ARC the objects will be released (unless you return a reference to an object from the method). In MMR you would need to manually send release message to destroy the objects.
I am pretty new to Objective-C and iOS-development, and I am currently trying to grasp how to do memory-management. My app in non-ARC btw.
This object is not declared anywhere in the code (not .h or anything) other than the line belove. Do I need to release/dealloc this object in any way to clear the space for it when I am done using it, or is this done automatically?
NSMutableURLRequest *restRequest = [[NSMutableURLRequest alloc] init];
The same goes for this one. Not sure if this is the same question, but here I don't use the words alloc & init before using it. Does that make any difference?
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
In this case, I am defining the object in the .h-file as well as retaining it. Does this mean that the variable will always be in memory (when initialized once obsly) unless I release/dealloc it? I guess if that is the case, that is something I should do in views when the view is unloaded?
#interface Storeage : NSObject {
NSString *deviceToken;
}
#property (nonatomic, retain) NSString *deviceToken;
In the .m-file I will alloc and use this object like in the first or second case (does not seems to make any difference).
Please bear with me if this question is stupid. I am used to low level Java-programming with GC.
Do I need to release/dealloc this object in any way to clear the space for it when I am done using it, or is this done automatically?
Since you are not using ARC, you need to manually send it a release message in order to dispose of its ownership. (Good piece of advice: don't think in terms of "freeing memory". Reference counting means that you increase and decrease reference counts, you get to own and cease to own objects, the deallocation of an object upon having lost all its references is done automatically. In other words, release does not necessarily mean deallocation.)
The same goes for this one. Not sure if this is the same question, but here I don't use the words alloc & init before using it. Does that make any difference?
It does. You only own objects that you create using alloc, new, copy, mutableCopy or reference using retain. You do neither one here, so you don't have to worry about releasing it either. (Technically, it's an autoreleased instance that will be returned, the run loop will take care of it.)
In the .m-file I will alloc and use this object like in the first or second case (does not seems to make any difference).
Make the difference between instance variables and properties. A property setter method, if declared as retain or strong, will retain (increase the reference count of) your object. But that's true only if you use the accessor method, and not when you access the instance variable directly. If you wrote this:
variable = [[SomeObject alloc] init];
then you need to release it just like you would do with any other (local) variable:
[variable release];
If you use the accessor method to set it:
self.variable = [[[SomeObject alloc] init] autorelease];
then you have to use autorelease when creating it (else it will have a reference count of 2 and you'll leak memory).
In both cases, you can also use self.variable = nil; to relinquish ownership. This only works for properties.
All this radically changes with the introduction of ARC, which I don't explain here for three reasons:
I'm not an ARC expert by any means;
I'd like to encourage you to learn MRC (which you seem to have the intention to) perfectly before trying ARC;
It was not the question.
I've people who use [variable release] and some other times variable = nil to clean up memory?
When do you use each one? and what are the differences?
variable = nil; will not release memory. self.property = nil; will release memory if [self setProperty:nil]; would, for example a synthesized property with the retain attribute. Calling [variable release]; will always release one reference of an object.
Depends on what you mean by "clean up memory".
release is the only thing that frees dynamically allocated memory allocated by alloc. alloc should always be paired with a call to release or autorelease somewhere.
Setting a varible to nil does not necessarily free any memory (see drawnonward's answer), and can be a source of memory leaks.
When you see a variable set to nil, it's about preventing it from accidentally being used later after its memory has been freed (this can cause crashes). While you can always set a variable to nil after a call to release, it's somewhat a matter of style when it's actually necessary. For example, you don't often see variables set to nil in the dealloc method of a class, since by that point an object won't be able to accidentally misuse such a variable anymore, since it's being nuked.
If a property is set to retain, then these 3 are equivalent:
[self setProperty:nil];
self.property = nil;
[property release]; property = nil;
In each case, the object will be released, and then set to nil so that all access to the object from then on will not be allowed. "nilling" the instance variable is handy since it ensures you can only ever release the object once in this context because calling self.property = nil twice will do nothing the second time, but calling [property release] will release the object twice even though you likely only retain it once.
Most of the time I find it least bug prone to let retain properties do their thing and try to stay away from explicit retain and release calls most of the time.