Objective-C Memory Management Being Exceptional Exception Handling and Memory, memorymanagement
Objective-C Memory Management Being Exceptional Exception Handling and Memory
3.1 Cocoa requires that all exceptions must be of type NSException
Cocoa requires all exceptions of the NSException type.
So even though you can throw an exception from other objects, Cocoa isn' t set up to deal with those.
So even if you throw an exception from another class, cocoa will not handle it.
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 shoshould throw and catch exceptions in your code, instead of lemo-them escape to the framework level.
The cocoa framework usually uses an existing program to solve the exception. You should throw and catch exceptions in your own code, instead of running them to the framework layer.
To enable support for exceptions, make sure the-fobj-exceptions flag is turned on.
To support exceptions, make sure that-fobj-exceptions is enabled.
When an exception is thrown and is not caught, the program stops at the exception point and propagates the exception.
When an exception is thrown and is not received, the program stops at the exception point.
3.2 Keywords for exceptions
All the keywords for exceptions start with @. Here's what each one does
Therefore, all keyword exceptions start.
(1) @ try: Defines a block of code that will be tested to determine if an exception
Shocould be thrown.
Test whether an exception should be thrown.
(2) @ catch (): Defines a block of code for handling a thrown exception. Takes
Argument, typically of type NSException, but can be of other types.
Exception Handling
(3) @ finally: Defines a block of code that gets executed whether an exception is
Thrown or not. This code will always be executed.
Whether or not an exception is thrown.
(4) @ throw: Throws an exception.
Throw 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.
You can select the @ catch type based on the exception type.
@ 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:
A program throws an exception by creating NSException and using the following technology:
(1) Using @ throw exception;
(2) Sending a raise message to an NSException objectwe'll create an exception: we create an NSExcepiton
NSException * theException = [NSException exceptionWithName:...];
We can then throw with either We throw through the following:
@ Throw theException;
Or
[TheException raise];
You'll usually throw exceptions from inside the exception handling code.
You can also throw an exception in an exception handling code.
@ Try {
NSException * e = ...;
@ Throw e ;}
@ Catch (NSException * e ){
@ Throw; // rethrows e.
}
2.4 Exceptions need memory management too. memory management is also required for Exceptions
Memory management can be tricky when tions 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.
Suppose processDictionary throws an exception, but the dictionary has not been released, so memory leaks.
Solution: 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 ).
Process at @ finally, because it is always executed.
-(Void) mySimpleMethod
{
NSDictionary * dictionary = [[NSDictionary alloc] initWith...];
@ Try {
[Self processDictionary: dictionary];
}
@ Finally {
[Dictionary release];
}
}
2.5 Exceptions and autorelsponpools Exceptions and automatic release 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 are almost always created for automatic release because you don't know when it will end.
-(Void) myMethod
{
NSAID utoreleasepool * pool = [[NSAID utoreleasepool 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 tions in the @ catch block, which causes the @ finally block to execute before the exception is rethrown.
We can rethrow conditions in @ catch block. This causes @ finally to be executed before the exception is thrown.
This will cause the local pool to be released before the exception can be delivered, thus turning it into a dreaded zombie exception.
This will cause a horrible zombie exception.
-(Void) myMethod
{
Id savedException = nil;
NSAID utoreleasepool * pool = [[NSAID utoreleasepool 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.
With retain, we keep this exception in the parent pool.