Copyright Notice
This article is copyrighted by Vince yuan (Vince. Yuan # gmail.com. For non-profit reprinting, the original link http://vinceyuan.cnblogs.com/must be included, and the content of this copyright should be included.
Version 1.1 was published on
Preface
When I was a beginner at objectice-C, I always felt confused about the memory management mechanism of objective-C. The program often experienced memory leaks or inexplicable crashes. I have summarized my research achievements and experience on the objective-C memory management mechanism, and wrote such a simple tutorial. I hope it will be helpful to you and you are welcome to discuss it together.
The memory management involved in this article is for Classes inherited from nsobject.
Basic Principles
Objective-C's memory management mechanism is different from the fully automatic garbage collection mechanism of. Net/Java. It is essentially a manual management method in C language, but it only adds some automatic methods.
1. The objective-C object is generated on the heap. After being generated, a pointer is required to point to it.
Classa * obj1 = [[classa alloc] init];
2. The objective-C object will not be automatically destroyed after use. You need to execute dealloc to release space (destroy); otherwise, the memory will be leaked.
[Obj1 dealloc];
This brings about a problem. In the following code, does obj2 need to call dealloc?
Classa * obj1 = [[classa alloc] init];
Classa * obj2 = obj1;
[Obj1 Hello]; // output hello
[Obj1 dealloc];
[Obj2 Hello]; // can this row and the next row be executed?
[Obj2 dealloc];
No, because obj1 and obj2 are just pointers. They point to the same object. [obj1 dealloc] has destroyed this object and cannot call [obj2 Hello] or [obj2 dealloc]. Obj2 is actually an invalid pointer.
How to Avoid invalid pointers? See the next one.
3 objective-C uses the reference count (ref count or retain count ). The number of times the object is referenced. For example, if an object is pointed to (referenced) by two pointers, its retain count is 2. To destroy an object, call release instead of dealloc. Release will reduce retain count by 1. Only when retain count is equal to 0 will the system call dealloc to actually destroy this object.
Classa * obj1 = [[classa alloc] init]; // when an object is generated, retain COUNT = 1
[Obj1 release]; // release: reduce retain count by 1, retain COUNT = 0, dealloc is automatically called, and the object is destroyed
Let's look back at the problem with the Invalid Pointer and change dealloc to release?
Classa * obj1 = [[classa alloc] init]; // retain COUNT = 1
Classa * obj2 = obj1; // retain COUNT = 1
[Obj1 Hello]; // output hello
[Obj1 release]; // retain COUNT = 0, the object is destroyed
[Obj2 Hello];
[Obj2 release];
After [obj1 release], obj2 is still an invalid pointer. The problem persists. For the solution, see the next one.
4 when the objective-C pointer is assigned a value, retain count will not be automatically added and manual retain is required.
Classa * obj1 = [[classa alloc] init]; // retain COUNT = 1
Classa * obj2 = obj1; // retain COUNT = 1
[Obj2 retain]; // retain COUNT = 2
[Obj1 Hello]; // output hello
[Obj1 release]; // retain COUNT = 2-1 = 1
[Obj2 Hello]; // output hello
[Obj2 release]; // retain COUNT = 0, object destroyed
Solve the problem! NOTE: If [obj2 release] is not called, The retain count of this object is always 1 and will not be destroyed, causing memory leakage. (1-4 can refer to the example program memman-no-pool.m in the attachment)
It does not leak memory, but it seems a little troublesome. Is there a simple way? See the next one.
5. The autorelease pool (automatically released Object pool) is introduced in objective-C. objects can be automatically released when some rules are followed. (Autorelease pool is still not the fully automated garbage collection mechanism of. Net/Java)
5.1 for newly generated objects, you only need to call autorelease. You do not need to call release any more!
Classa * obj1 = [[classa alloc] init] autorelease]; // retain COUNT = 1 but no need to call release
5.2 For pointer assignment, the code is similar to the previous one.
Classa * obj1 = [[classa alloc] init] autorelease]; // retain COUNT = 1
Classa * obj2 = obj1; // retain COUNT = 1
[Obj2 retain]; // retain COUNT = 2
[Obj1 Hello]; // output hello
// For obj1, you do not need to call (actually cannot call) Release
[Obj2 Hello]; // output hello
[Obj2 release]; // retain COUNT = 2-1 = 1
Careful readers will surely find that this object has not been destroyed. When will it be destroyed? Who will destroy it? (Refer to the example program memman-with-pool.m in the attachment) see the next one.
6 autorelease pool principle analysis. (In fact, it is very simple. You must stick to it. Otherwise, you still cannot understand the objective-C memory management mechanism .)
6.1 autorelease pool is not born and needs to be created manually. Only when you create an iPhone project, xcode will automatically help you write it. The real name of autoreleasepool is NSAID utoreleasepool.
NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init];
6.2 The nsmutablearray array is contained in the nsmutoreleasepool to save all objects declared as autorelease. If an object is declared as autorelease, the system will add this object to this array.
Classa * obj1 = [[classa alloc] init] autorelease]; // retain COUNT = 1, add this object to autorelease pool
6.3 when the NSAID utoreleasepool itself is destroyed, it traverses this array and each member in the release array. If the retain count of the members in the array is 1 at this time, after release, the retain count is 0, and the object is destroyed. If the retain count of the members in the array is greater than 1 at this time, the retain count is greater than 0 after release, and the object is still not destroyed, causing memory leakage.
6.4 by default, there is only one autorelease pool, which is usually similar to the following example.
Int main (INT argc, const char * argv [])
{
NSAID utoreleasepool * pool;
Pool = [[NSAID utoreleasepool alloc] init];
// Do something
[Pool release];
Return (0 );
} // Main
All objects marked as autorelease are destroyed only when the pool is destroyed. If you have a large number of objects marked as autorelease, this obviously cannot make good use of the memory, it is very easy to cause insufficient memory in iPhone memory-constrained programs. For example:
Int main (INT argc, const char * argv [])
{
NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init];
Int I, J;
For (I = 0; I <100; I ++)
{
For (j = 0; j <100000; j ++)
[Nsstring stringwithformat: @ "1234567890"]; // The generated object is autorelease.
}
[Pool release];
Return (0 );
} // Main
(You can refer to the example program memman-many-objs-one-pool.m in the attachment, through the monitoring tool at runtime you can find that there is a sharp increase in the use of the internal, until the pool is released upon destruction) You need to consider the next one.
7. Multiple autorelease pools can be nested in the objective-C program. When you need to create a large number of local variables, you can create an embedded autorelease pool to release the memory in time. (Thanks to hhyytt and neogui, in some cases, the system will automatically create the autorelease pool. See chapter 4)
Int main (INT argc, const char * argv [])
{
NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init];
Int I, J;
For (I = 0; I <100; I ++)
{
NSAID utoreleasepool * looppool = [[NSAID utoreleasepool alloc] init];
For (j = 0; j <100000; j ++)
[Nsstring stringwithformat: @ "1234567890"]; // The generated object is autorelease.
[Looppool release];
}
[Pool release];
Return (0 );
} // Main
(You can refer to the example program memman-many-objs-many-pools.m in the attachment for minimal memory usage changes)
Sample Code File Link: http://files.cnblogs.com/VinceYuan/objective-c-memman.zip