Its very common question everybody familiar with, but I'm still not understand it fully.
If Object A owns (have a strong property of) Object B, and Object B have a strong property of object A, there is retain cycle, and no object can be released and there is a memory leak.
But, what if Object A instead will point for Object C instead of Object B, therefore another address in memory?
As far as i know, strong properties do something like follow:
- (void)setObject:(id)newObject{
if (_newObject == newObject){
return; //
}
NSObject *oldObject = _newObject;
_newObject = [newObject retain];
[oldObject release];
}
So, what if we point instead for Object C, isn't in that case memory for Object B will be released? What if both Objects (A and B) will instead set nil object? Is there still would be retain cycle with memory leak? With old value "floating" somewhere in memory?
I know, that has been discussed many times, but i still can't get "whole picture" in my head. I would appreciate any clarification in that matter.
The word you are looking for is "retain cycle".
The simplest retain cycle would be an object having a strong reference to itself. Very rare because it is rather pointless.
The most common case is A having a strong reference to B and B having a strong reference to A. A->B->A. You see the cycle?
The cycle can be any length A->B->C->D->E->F->G->...->A. It's a retain cycle, so nothing will be released. If you have just A->B->C->D->...->Z with no reference back to another object in the sequence, then there is no cycle. No cycle, no problem.
If the question is "can you break a retain cycle by reassigning one of the properties?", the answer is yes. This applies equally if you assign nil to the property.
Related
My knowledge of ARC has been tested today, i stumbled on this article and it has an example under the heading "Nesting of statements" which in my mind seems wrong.
In the example they show embedded above, the line highlighted with a green underline says that the string alloced inside the function would first get a retain count +1 when being created, then +1 again when adding to the array, then once the array is nil'ed after the for loop, the retain count of the string would be reduced by 1, leaving the original string with a retain count of 1, thus not being dealloced.
I would have assumed the compiler would have been smart enough to at least make an object like that not actually have a retain count initially, since if you just had
[[NSString alloc] initWithFormat:#"Name 1"]];
this string being alloced would have nothing pointing to it and would be released when the autorelease pool comes to an end instead of having a retain count of 1 forever. so why would it have different behaviour when its in a parameter of a function? (unless that line does have a retain count of 1 and this is somehow a memory leak? otherwise it could have a retain count of 1 till the end of its scope at most surely, but then that logic would apply if its a parameter as well i would assume)
Is this article wrong or is my understanding of ARC flawed?
The article is wrong.
Your understanding is essentially correct, though the autorelease pool is not used in this case. The sub-expression:
[[NSString alloc] initWithFormat:#"Name 1"]];
returns an owned object, as do all init methods. That object is passed to addObject: and the array also takes ownership. After that ARC sees the string is no longer required by the method and relinquishes its ownership - leaving the array as the only owner.
HTH
ARC is not flawed here. Sounds like the article is wrong.
ARC will release the allocated parameter object as expected while the array keeps its reference. Once the array is released, the object will have no more references and it will also be deallocated, as expected.
I have an instant variable "obj1" in MyClass.h.
#property (nonatomic, retain) NSMutableArray *arrObj1;
and in MyClass.m viewDidLoad method, i have allocated another object "obj2" and assign that to obj1.
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *arrObj2 = [[NSMutableArray alloc] initWithObjects:#"a",#"b",#"c", nil];
NSLog(#"arrObj2 count %lu",(unsigned long)[arrObj2 retainCount]);
self.arrObj1 = arrObj2;
NSLog(#"arrObj1 count %lu",(unsigned long)[self.arrObj1 retainCount]);
NSLog(#"arrObj2 count %lu",(unsigned long)[arrObj2 retainCount]);
}
Here is the output
2015-08-19 11:06:14.461 MyClass[1812:24133] arrObj2 count 1
2015-08-19 11:06:16.332 MyClass[1812:24133] arrObj1 count 2
2015-08-19 11:06:17.327 MyClass[1812:24133] arrObj2 count 2
I am not getting how arrObj2 get retain Count value 2.
please explain me.
Thank you
A more relevant question to your problem is: Why do arrObj and arrObj2 seem to share properties? And the answer is they're two references to the same object. That means the same array is referenced strongly in the same place; that is, arrObj1 and arrObj2 are actually the same array. That's why you see a retainCount of 2, though you shouldn't use retainCount for this. (More on that later.) Compare the addresses of the arrays in the debugger instead; they will be the same. If you add an object to one array, it'll be added to "the other."
You can fix that by using copy on the property declaration instead, or by changing self.arrObj1 = arrObj2 to self.arrObj1 = [arrObj2 mutableCopy] . (Edit: I'm not actually sure changing the property type to copy will help here, since it's a mutable type. It would work if it was just an NSArray, though.)
I hope that answers your question, but now I want to explain why it's the wrong question. Please don't take any offence, because learning this is important and not easy. :)
Think in terms of relationship type, not retain/release
You shouldn't be thinking in terms of retain counts at all, but in terms of strong and weak relationship: A strong relationship expresses an ownership interest in the object, a weak relationship doesn't and will be converted to nil shortly after all ownership interests in the object are removed. Also, note that the retain property type is deprecated: it should be strong in ARC code.
Don't use retainCount.
Don't use retainCount. Or, if you prefer, When to use Retain Count:
Never.
Then there's Apple's official documentation, which begins:
This method is of no value in debugging memory management issues.
Or there's this from bbum, which I consider even better. He goes into great detail about why retainCount is useless, concluding with:
Bottom line: the only time the absolute retainCount can be conclusively used for analytic purposes is if you have the backtrace of every retain and release that contributed to the current retain count’s value (there is another use case, documented at the end). If you have that, then you don’t need the retain count and, fortunately, Instruments is already generally quite adept at producing a per-object inventory of retains and releases for you.
Basically, it's value is not useful. It will return (in some cases) the number of times an object has been retained without releasing. It does not (and can not) take the number of times it has been autoreleased into account. And it will not always return the "correct" value even without considering autorelease, since some objects can never be deallocated from RAM.
in Objective-C an object is a reference type.
The retain count is increased the first time when the object was allocated.
When the object is assigned to arrObj1 the object is not copied when the property is declared as retain or strong so arrObj1 and arrObj2 contain the pointer to the same object. The implicit setter of the property arrObj1 increases the retain counter a second time.
Memory management is the programming discipline of managing the life cycles of objects and freeing them when they are no longer needed.
Managing object memory is a matter of performance; if an application doesn’t free unneeded objects, its memory footprint grows and performance suffers.
Memory management in a Cocoa application that doesn’t use garbage collection is based on a reference counting model. When you create or copy an object, its retain count is 1.
Thereafter other objects may express an ownership interest in your object, which increments its retain count.
The owners of an object may also relinquish their ownership interest in it, which decrements the retain count. When the retain count becomes zero, the object is deallocated (destroyed).
Check this image.
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Art/memory_management.jpg
Hope this help.
After the statement
self.arrObj1 = arrObj2;
the variable arrObj2 and the property self.arrObj1 point to the very same object.
If they point to the same object, and arrObj2 has a reference count of 2, what reference count do you expect self.arrObj1 to have?
Reason why retain count is coming as 2 is because you have used retain for NSMutableArray *arrObj1, so in effect
when you allocate arrObj2 retain count become 1,
the when you assign it to arrObj1 as its having a retain property, count increase - becoming 2.
arrObj2 is same arrObj1 as you have not copied it (as Steven Fisher in above answer pointed out) both has same retain count.
If you make arrObj1 to assign property then count will be remained as 1.
Simply put, the object pointed to by arrObj2 is the same object pointed to by arrObj1. Instruments shows us that this object gets +1 retain count when you called initWithObjects:
And that it got +2 retain count when you called setArrObj1 (i.e. you used the self.arrObj1 = ... syntax):
For demonstrations using Instruments' "Allocations" tool for tracking memory usage, see WWDC 2013 video Fixing Memory Issues and WWDC 2012 video iOS App Performance: Memory. Bottom line, while it will take some practice to efficiently find the correct objects in the "Allocations" tool, this "Record reference counts" feature is invaluable in finding where the strong references to the objects in question were established.
I'm sure you've seen it, but I'd also refer you to the Advanced Memory Management Programming Guide.
When you alloc a new memory area (I call it M) and assign it to obj2, the retainCount of M is 1.
When you do: self.obj1 = obj2.
Because self.obj1 is a retain property, so M will be retain +1, so its retainCount = 2 now.
Cause obj1 & obj2 are references to M, so their retainCount are 2.
Let try [obj1 release] and get retainCount of obj2 again to check.
Hope it helps.
If we type
MyObject *obj = [[MyObject alloc] init];
"obj" is a pointer to the memory address.
...When we create an int, we type:
int x = 10;
Why don't we type?
int *x = 10;
The question is, why do we need a pointer to object and not int, float, etc...
Efficiency.
Moving an int from one place to another is easy. Moving an object needs a little bit more work from the CPU. Moving the address of an object is as easy as moving an int.
In plain C, it is common to handle pointers to structs for the same reason. C makes it easy with the -> operator.
There are languages where you can create objects “without a pointer”, on the stack. C++, for example. One great thing about having objects on the stack is that they get automatically deallocated when the scope ends, which helps with memory management. It’s also faster.
One bad thing about having objects on the stack is that they get automatically deallocated when the scope ends and the stack disappears. And since objects are usually longer-lived than local variables, you would have to copy the object’s memory somewhere. It’s entirely possible, but it complicates matters.
And it’s not just the memory lifecycle that’s complicated with stack-based objects. Consider assignment, foo = bar for two object types. If the objects are always pointers (Class*), you just assigned a pointer and got two pointers to the same objects; easy. If foo is stack-based (Class), the assignment semantics starts to get blurry – you could well end with a copy of the original object.
Introducing a rule that all objects are allocated on the heap (“with pointers”) is a great simplification. And as it happens, the speed difference doesn’t matter that much, and the compiler can now also automatically insert code to deallocate heap-based objects after they go out of scope, so it’s generally a win-win situation.
You can have pointer for int, float as well.
Objects are created on heap. To access it, you need the address. Thats why they are of pointer types.
Because that is the nature of an object.
Objective-C is directly derrived from C. That is why objects are referred to as pointers. An int-type variable of the size of an memory address is a pointer.
In the end, an object in memory is not much different from an struct in memory.
However, when working in Objective-C it is advisable to think of these variables as references of objects rather than pointers to an object's memory areas. Think of them like Java does and do not spend much thoughts on how the system manages the references. There are far more important things to think of such as alloc/retain vs. release/autorelease or following the much easier ARC rules respectively.
BTW:
MyObject obj;
That would declare an object, not a pointer. It is not possible in Objective-C (afaik) and certainly not reasonable. But if it was reasonable and possible, that is what the syntax would look like.
int *x;
That does create a pointer to an int. For using it you would have to allocate memory and assign its address to x. Rarerly reasonable in Objective C either but quite useful in standard C.
its the difference between objects being on the stack or the heap.
going int x = 10 x is now on the stack. int *x = 10 is just simply wrong (well most likely not what you want) since that is declaring a pointer to address 10 whatever that may be. you would want int *x = malloc(sizeOf(int)); as CodaFi suggested. that will allocate memory on the heap of the size of an int.
going MyObject *obj = [[Myobject alloc] init]; the compiler behind the scenes is allocating your object to the heap for you, but its basically the same principle
Dynamic arrays are reference counted, and so the memory is freed automatically by the compiler. My question is, when exactly does this automatic freeing occur? Does it happen immediately, or at the end of the containing procedure?
Here is a concrete example
procedure DoStuff;
var data:TBytes;
begin
data:=GetData; // lets say data now contains 1 Gig of data.
DoStuffWithData(data);
// I now want to free up this 1Gig of memory before continuing.
// Is this call needed, or would the memory be freed in the next line anyway?
Finalize(data);
data:=GetMoreData; // The first array now has no remaining references
DoStuffWithData(data);
end
Is the call to Finalize() redundant?
The call to Finalize isn't quite redundant. It's true that the dynamic array's reference count will be decremented on the next line (therefore destroying the array, probably), but that will only happen after the new dynamic array is allocated. Just before the return of GetMoreData, but before the assignment takes place, there will be two dynamic arrays in memory. If you destroy the first one manually in advance, then you'll only have one array in memory at a time.
The second array that you store in data will get destroyed as DoStuff returns (assuming DoStuffWithData doesn't store a copy of the dynamic-array reference elsewhere, increasing its reference count).
When exactly does this automatic freeing occur? Does it happen immediately, or at the end of the containing procedure?
Dynamic memory associated with managed types (dynamic arrays fall into this class) is freed when the reference count is set to 0. This can happen at the following points:
The reference variable is assigned a new value. A call to Finalize can be thought of as the special case where the new values is nil.
The reference variable goes out of scope. For example:
The exit of a function is reached; local variables go out of scope.
An object is destroyed and its members go out of scope.
A pointer to a record is destroyed with the Dispose function; all fields of the record go out of scope.
A unit is finalized and all global variables defined in the unit are finalized.
Note that the various cases above only result in memory being freed when the reference that is being finalized or is leaving scope is the last remaining reference. In other words, when the reference count is 1.
In your specific example, assuming the Finalize is removed, you are creating a new dynamic array and assigning it to a variable that already holds a dynamic array. This then falls into the class described by item 1 in the list above. So in that sense the call to Finalize is superfluous.
Rob has explained the order in which the allocation and deallocation happens which is a good point. To the best of my knowledge that is an implementation detail that is not explicitly documented. However, I'd be astounded if that detail was ever changed.
I was wondering if someone could tell what happens with regards to memory when the following happens:
Dict = New Dictionary --- Col = New Collection
Dict.Add Key, CustomClassOne
Dict.Add Key2, CustomClassTwo
Dict.Add Key3, CustomClassThree
Dict.Remove Key3
At this point is Key3 removed from memory or would I have to Set Dict.Item(Key3) = Nothing to remove it from memory?
Set Dict = Nothing '// will this remove All the above added custom class objects?
Set Col = Nothing '// Same question as above
Ugh VB memory management.... TY for your time,
- Austin
VB is reference counted.
The rules of when an object is released from memory is simple.. it happens when there are no more references to that object. Each time an object goes out of scope (such as the end of a function) its reference count is decreased; which may in turn cause any objects which were referenced by this object to have their reference counts decreases too; and if their reference counts get to 0, they too are released from memory.
This is why there is usually no need to set an object's reference to Nothing... that will decrease its reference count, but that will also happen when it goes out of scope.
So to answer your question:
Dict.Remove Key3 is all that is required to remove CustomClassThree and Key3 from memory (as long as you don't have other references pointing to this object).
Set Dict = Nothing will remove everything from memory, but this would happen anyway when it goes out of scope (again assuming there are no other references pointing to the objects it contains).
Col doesn't seem to have much to do with the other statements and would be removed from memory when it goes out of scope without needing to set Col = nothing
Note:
The purpose of setting a reference to nothing is only really useful if you have objects which both have references to each other. Look up circular references for the details
With both Scripting.Dictionary and Collection instances when the last reference to the object is gone then the object references they hold are released. Whether or not the objects themselves are deallocated depends on whether or not another variable holds a reference to the same object.
Think of each reference as a rope holding a rock above an abyss. Until the last rope is cut the rock doesn't drop out of existence.
Removing an item from a Dictionary or Collection cuts that one rope.