Objective-C Memory Management Being Exceptional 異常處理與記憶體,memorymanagement
Objective-C Memory Management Being Exceptional 異常處理與記憶體
3.1Cocoa requires that all exceptions must be of type NSException
cocoa 需要所有的異常是NSException類型的。
so even though you can throw an exception from other objects, Cocoa isn't set up to deal with those.
所以你即使從別的類拋出異常,cocoa 也不會處理。
Exception handling is really intended for errors that are generated by your programs. Cocoa frameworks usually handle errors by exiting the program, which is not what you want. You should throw and catch exceptions in your code, instead of letting them escape to the framework level.
cocoa架構通常用已經存在的程式解決異常。你應該throw and catch exceptions 在你自己的代碼中,而不是任其跑到架構層。
To enable support for exceptions, make sure the -fobj-exceptions flag is turned on.
為了支援異常,你應該確保-fobj-exceptions開啟。
When an exception is thrown and is not caught, the program stops at the exception point and propagates the exception.
當一個異常拋出後,並沒有被接到的話,則程式停在異常點。
3.2 Keywords for exceptions
All the keywords for exceptions start with @. Here's what each one does
所以的異常keyword 均以@開頭。
(1)@try: Defines a block of code that will be tested to determine if an exception
should be thrown.
測試一個異常是否應該被拋出。
(2)@catch(): Defines a block of code for handling a thrown exception. Takes an
argument, typically of type NSException, but can be of other types.
處理異常
(3)@finally: Defines a block of code that gets executed whether an exception is
thrown or not. This code will always be executed.
不管是否拋出異常都運行。
(4)@throw: Throws an exception.
拋出異常
3.3 Catching Different types of exceptions
You can have multiple @catch blocks depending on which type of exception you want to handle.
可以根據exception 的類型來選擇@catch 的類型
@try{
} @catch (MyCustomException *custom) {
} @catch (NSException *exception) {
} @catch (id value) {
} @finally {
}
A program throws an exception by creating an instance of NSException and using one of two techniques:
一個程式拋出異常通過建立NSException 和使用下面的技術:
(1)Using @throw exception;
(2)Sending a raise message to an NSException objectwe'll create an exception: 我們建一個NSExcepiton
NSException *theException = [NSException exceptionWithName: ...];
We can then throw with either 我們throw 通過下面:
@throw theException;
or
[theException raise];
You'll usually throw exceptions from inside the exception handling code.
也可以在一個exception handling code裡再拋出異常。
@try {
NSException *e = ...;
@throw e; }
@catch (NSException *e) {
@throw; // rethrows e.
}
2.4 Exceptions need memory management too . 異常也需要記憶體管理
Memory management can be tricky when exceptions are involved.
- (void)mySimpleMethod
{
NSDictionary *dictionary = [[NSDictionary alloc] initWith....];
[self processDictionary:dictionary];
[dictionary release];
}
let's imagine that processDictionary throws an exception. The program jumps out of this method and looks for an exception handler. But because the method exits at this point, the dictionary object is not released, and we have a memory leak.
假如processDictionary 拋出異常,但是dictionary 還沒有釋放,因此有了memory leaks .
解決辦法:One simple way to handle this is to use @try and @finally, doing some cleanup in @finally because it's always executed (as we said earlier).
在@finally 處處理,因為總是執行。
- (void)mySimpleMethod
{
NSDictionary *dictionary = [[NSDictionary alloc] initWith....];
@try {
[self processDictionary:dictionary];
}
@finally {
[dictionary release];
}
}
2.5 Exceptions and autorelease pools 異常和自動釋放池
Exceptions are almost always created as autoreleased objects because you don't know when they will need to be released. When the autorelease pool is destroyed, all objects in that pool are destroyed also, including the exception.
Exceptions 幾乎總是被創作為自動釋放因為你不知道什麼時候結束。
- (void)myMethod
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary *myDictionary =
[[NSDictionary alloc] initWithObjectsAndKeys:@"asdfads", nil];
@try {
[self processDictionary:myDictionary];
} @catch (NSException *e) {
@throw;
} @finally {
[pool release];
}
}
There's a problem when we think about exception handling. We discussed earlier that we can rethrow exceptions in the @catch block, which causes the @finally block to execute before the exception is rethrown.
我們可以rethrow exceptions 在@catch block中。這導致了@finally在異常拋出前執行。
This will cause the local pool to be released before the exception can be delivered, thus turning it into a dreaded zombie exception.
這將導致恐怖的zombie exception.
- (void)myMethod
{
id savedException = nil;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary *myDictionary =
[[NSDictionary alloc] initWithObjectsAndKeys:@"asdfads", nil];
@try {
[self processDictionary:myDictionary];
} @catch (NSException *e) {
savedException = [e retain];
@throw;
} @finally {
[pool release];
[savedException autorelease];
}
}
By using retain, we saved the exception in the parent pool. When our pool is released, we already have a pointer saved, and when the parent pool is released, the exception will be released with it.
通過retain ,我們保留了這個exception 在parent pool。