Executing cleanup code? - objective-c

Generally speaking goto is bad (we all know why) What would be a better way to implement a simple cleanup on an error (as in the example below) without having to duplicate the code. To my mind the code below is fine, I was just curious what others would do:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]
int returnCode = 0;
// ... Other code
// WRITE: To file
if([dataStore writeToFile:savePathData atomically:YES] == NO) {
NSLog(#"writeToFile ... Error");
returnCode = 1;
goto cleanUpCode;
}
// ... Other code
// Clean up
cleanUpCode:
[archiver release];
[newPlanet release];
[pool drain];
return(returnCode);
}
EDIT_001:
In general terms I agree that #try, #catch, #finally are more than certainly the way to go but I do have two small concerns.
(1) The three #try, #catch, #finally blocks must all be together, you don't have the flexibility to place code between the #catch and #finally that you might want to bypass.
(2) Apple's documentation for Obj-C 2.0 states the following: "Important: Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors (such as a file not being accessible)".
much appcreciated
gary

This is a common idiom in C code, and I don't think there is anything wrong with it in the absence of a language with more comprehensive creation/destruction semantics.
Goto is considered harmful in the general sense; it can make program execution difficult to follow. Here, it's very limited in scope, and the flow is unidirectional. It's also helpful in the sense that it allows you to localize your cleanup code, which is a good thing.

Well, first of all I would try to refactor it into some more methods, maybe then the code would not be so illegible?
Also, you can always use autoreleased objects and so you only need the [pool drain] at the end. And this can probably be done using #try/#finally, so that you can just return 1 instead of returnCode = 1.
E.g. take a look at the Exception Handling and Memory Management document (I know your question is not about exceptions, but this is basically all the same) - they recommend something like this:
- (void)doSomething {
NSMutableArray *anArray = nil;
array = [[NSMutableArray alloc] initWithCapacity:0];
#try {
[self doSomethingElse:anArray];
}
#finally {
[anArray release];
}
}
Personally, this is what I would do.

There are many ways to do this. Here's a couple:
Write a procedure corresponding to your main code, e.g. RunApplication. Put the call to it in the "else" branch.
Put it in a try/catch, do the error handling in the "catch" section, normal processing otherwise.
Code
e.g. try {
.. check for error (any function/procedure that checks for an error can throw an exception
.. do normal processing (still a good idea to factor this out into a procedure, for clarity
}
catch {
.. handle errors
}
finally
{
.. do cleanup
}
Anytime you think you need a goto, for an error case, you will probably find that a try/catch and exception works better.
In languages without try/catch, just use refactoring.

As you are describing something that looks like a small command line program I wouldn't worry about it. Because when your program ends all memory allocated by the program will be returned to the system (it will cease to exist). But, if you had a bigger program that allocates a lot and runs for a while you might look into cleaning more correctly as it can help tracking down memory leaks which could affect a program that runs a longer time. In that case I'd also suggest using some macros.
#define THROW( _name ) goto label_ ## _name
#define CATCH( _name ) label_ ## _name:
:
:
if([dataStore writeToFile:savePathData atomically:YES] == NO) {
NSLog(#"writeToFile ... Error");
returnCode = 1;
THROW( cleanUpCode );
}
:
:
CATCH( cleanUpCode )
[archiver release];
[newPlanet release];
[pool drain];

Related

Objective C - caller Object of a method [duplicate]

Example: When my method -fooBar gets called, I want it to log in the console which other method of which other class called it.
Right now, I only know how to log the method name of fooBar itself and it's class, with this:
_cmd
[self class]
Is this possible to figure out?
In fully optimized code, there is no 100% surefire way to determine the caller to a certain method. The compiler may employ a tail call optimization whereas the compiler effectively re-uses the caller's stack frame for the callee.
To see an example of this, set a breakpoint on any given method using gdb and look at the backtrace. Note that you don't see objc_msgSend() before every method call. That is because objc_msgSend() does a tail call to each method's implementation.
While you could compile your application non-optimized, you would need non-optimized versions of all of the system libraries to avoid just this one problem.
And this is just but one problem; in effect, you are asking "how do I re-invent CrashTracer or gdb?". A very hard problem upon which careers are made. Unless you want "debugging tools" to be your career, I would recommend against going down this road.
What question are you really trying to answer?
How about this:
NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];
NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:#" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:#""];
NSLog(#"Class caller = %#", [array objectAtIndex:3]);
NSLog(#"Method caller = %#", [array objectAtIndex:4]);
Credits to the original author, intropedro.
It's not possible in the general case without actually walking the stack. There's not even a guarantee that another object send the message that called the method. For example, it could be called from a block in a signal handler.
NSLog(#"Show stack trace: %#", [NSThread callStackSymbols]);
See backtrace(3).
User the below method
Pass index for which you want to display method and pass -1 if you want to display full stack of method
+(void) methodAtIndex:(int)index{
void* callstack[128];
int frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
if (index == -1) {
for (int i = 0; i < frames; ++i) {
printf("%s\n", strs[i]);
}
}
else {
if (index < frames) {
printf("%s\n", strs[index]);
}
}
free(strs);
}
This information can be obtained using DTrace.
Make a macro that adds the __FUNCTION__ to the function name to the function call. This macro will then call your function with an extra parameter of a char* to the target function.
I was trying to catch who, how and when changes window's size and did some handwork:
- (void)logWindowWidth:(NSString *)whoCalls {
NSLog(#"%#", whoCalls);
NSLog(#"self.window.size.width %f", self.window.size.width);
}
-(void)someMethod {
[self logWindowWidth:#"someMethod - before"];
...
[self logWindowWidth:#"someMethod - after"];
}
-(void)anotherMethod {
[self logWindowWidth:#"anotherMethod - before"];
...
[self logWindowWidth:#"anotherMethod - after"];
}

Is the scope of what Xcode's "Build and Analyze" will catch as a leak supposed to be this limited?

It doesn't care about this:
NSString* leaker()
{
return [[NSString alloc] init];
}
I thought it would have been smart enough to check if any code paths could call that function without releasing its return value (I wouldn't normally code this way, I'm just testing the analyzer).
It reports this as a leak:
NSString* leaker()
{
NSString* s = [[NSString alloc] init];
[s retain];
return s;
}
but NOT this:
NSString* leaker()
{
NSString* s = [[NSString alloc] init];
// [s retain];
return s;
}
which seems particularly weak to me. Does it only analyze within the local scope? If the tool can't pick up on things like this, how can I expect it to pick up on actual mistakes that I might make?
clang does not perform any inter-procedure analysis, at least not yet. Even if it did, it might not necessarily catch this "error"- the permutations of potential code paths tends to rise super exponentially, making it a practical impossibility.
clang works with a set of heuristics that work "most of the time". Thankfully, Cocoa memory management rules tend to be fairly uniform, so the heuristics work for most uses. The specific example that you've given isn't really covered by the memory management rules, but I think most people (which includes myself) would tend to classify your example as "You've documented via the API that the caller of leaker() is responsible for releaseing the returned object". This is essentially analogous to - (NSString *)init... style methods.
clang knows that methods that begin with init... return an 'unreleased' object, and it is the callers responsibility to ensure that it is properly released. This forms part of the core of the heuristics- it doesn't need whole program or inter-procedural analysis to do the bulk of reference count checking- if a local block of code gets an object via an init... method, that local block of code needs to make sure it is properly released. Naturally, if the local block of code, and the object in question, is part of an init... method itself, it is covered by the same "rule", so it gets an exception.
What you probably want is something like:
NSString* leaker() __attribute__((ns_returns_retained))
{
return [[NSString alloc] init];
}
This lets the analyzer know that leaker() returns a 'retained' object, that the caller is responsible for properly releasing it. Although I haven't tested this, I strongly suspect that the 'leak' would be detected at the point where leaker() is called, i.e.:
void test(void)
{
NSString *leaked = leaker();
// Previous line should be caught as a "leak" by clang.
}
This is one of the unfortunate limitations of any static analyzer, not just clang.

How does #synchronized lock/unlock in Objective-C?

Does #synchronized not use "lock" and "unlock" to achieve mutual exclusion? How does it do lock/unlock then?
The output of the following program is only "Hello World".
#interface MyLock: NSLock<NSLocking>
#end
#implementation MyLock
- (id)init {
return [super init];
}
- (void)lock {
NSLog(#"before lock");
[super lock];
NSLog(#"after lock");
}
- (void)unlock {
NSLog(#"before unlock");
[super unlock];
NSLog(#"after unlock");
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyLock *lock = [[MyLock new] autorelease];
#synchronized(lock) {
NSLog(#"Hello World");
}
[pool drain];
}
The Objective-C language level synchronization uses the mutex, just like NSLock does. Semantically there are some small technical differences, but it is basically correct to think of them as two separate interfaces implemented on top of a common (more primitive) entity.
In particular with a NSLock you have an explicit lock whereas with #synchronized you have an implicit lock associated with the object you are using to synchronize. The benefit of the language level locking is the compiler understands it so it can deal with scoping issues, but mechanically they behave basically the same.
You can think of #synchronized as a compiler rewrite:
- (NSString *)myString {
#synchronized(self) {
return [[myString retain] autorelease];
}
}
is transformed into:
- (NSString *)myString {
NSString *retval = nil;
pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
pthread_mutex_lock(self_mutex);
retval = [[myString retain] autorelease];
pthread_mutex_unlock(self_mutex);
return retval;
}
That is not exactly correct because the actual transform is more complex and uses recursive locks, but it should get the point across.
In Objective-C, a #synchronized block handles locking and unlocking (as well as possible exceptions) automatically for you. The runtime dynamically essentially generates an NSRecursiveLock that is associated with the object you're synchronizing on. This Apple documentation explains it in more detail. This is why you're not seeing the log messages from your NSLock subclass — the object you synchronize on can be anything, not just an NSLock.
Basically, #synchronized (...) is a convenience construct that streamlines your code. Like most simplifying abstractions, it has associated overhead (think of it as a hidden cost), and it's good to be aware of that, but raw performance is probably not the supreme goal when using such constructs anyway.
Actually
{
#synchronized(self) {
return [[myString retain] autorelease];
}
}
transforms directly into:
// needs #import <objc/objc-sync.h>
{
objc_sync_enter(self)
id retVal = [[myString retain] autorelease];
objc_sync_exit(self);
return retVal;
}
This API available since iOS 2.0 and imported using...
#import <objc/objc-sync.h>
Apple's implementation of #synchronized is open source and it can be found here. Mike ash wrote two really interesting post about this subject:
Locks, Thread Safety, and Swift
Let's Build #synchronized
In a nutshell it has a table that maps object pointers (using their memory addresses as keys) to pthread_mutex_t locks, which are locked and unlocked as needed.
It just associates a semaphore with every object, and uses that.

Correct Structure to check for Errors using NSError

I'm coding up various routines and I'm trying my best to keep it neat and refactored.
Methods I'm creating are starting to look similar to this code:
-(IBAction)buttonPress:(id)sender {
// Create Document Shopping List with this document
[self doSomething:&error];
if(error) {
[NSApp presentError:&error];
return nil;
}
[self doSomethingElse:&error];
if(error) {
[NSApp presentError:&error];
return nil;
}
[self doYetSomethingElse:&error];
if(error) {
[NSApp presentError:&error];
return nil;
}
}
I love NSError, but this seems like an awfully clumsy way of handling all my errors.
A few thoughts I've had about alternative ways:
a) the error checking could be built into the methods doSomething, doSomethingElse etc, but then I wouldn't be able to exit the button press method without doing some kind of checking on the return value, which would lead me back to a similar structure.
b) I could set up the NSError as being Key Value Observed, but something about this feels deeply wrong. I'm very aware of the possibilities of abuse with KVO, so I'm trying to do everything without it whereever possible.
Surely I'm missing something really basic here? Is there a pattern that can help me? Or is this structure OK?
I think that none of the answers presented here are taking into account Apple's recommended practices.
Basically you should never check for the NSError object to determine if there was a problem. You check if there was a problem by checking the value returned from the method that takes a pointer to a pointer to an NSError.
From the Apple documentation:
Important Success or failure is indicated by the return value of the
method. Although Cocoa methods that indirectly return error objects in
the Cocoa error domain are guaranteed to return such objects if the
method indicates failure by directly returning nil or NO, you should
always check that the return value is nil or NO before attempting to
do anything with the NSError object.
The gist of your question is whether there are structural improvements you can make to your error handling. I think so, by essentially introducing more layers of nesting, either by extracting more code into separate methods/functions, or by introducing nesting in your high level sample method.
The idea is, when it comes to handling most errors, you probably are either interested in performing an alternate task, or in failing and propagating the error up the chain so that some responsible controller can convey the error to the user through UI.
Using this idea of "propagate or handle", I would rewrite your sample method like this:
-(IBAction)buttonPress:(id)sender {
// Create Document Shopping List with this document
[self doSomething:&error];
if(error == nil) {
[self doSomethingElse:&error];
if (error == nil) {
[self doYetSomethingElse:&error];
}
}
if(error) {
[NSApp presentError:&error];
}
}
Note that there are good arguments against introducing too much nesting in a particular method. Nesting such as this is essentially a short alternative to extracting methods. It might make more sense, for instance, that "doSomething:" itself calls doSomethingElse:, which calls doYetSomethingElse: for instance. This would impose the same structure on the code as the if-nest, but would be arguably more maintainable.
As an aside, I am not a fan of inline return statements. In this particular instance, the sample method doesn't actually call for a return value, but if it did, I prefer to set a local variable to the returned value and only return at the end of the flow control. Jumping out of a function or method prematurely is a sure way to encounter weird bugs, IMHO.
I think the real question is how much granularity you need in your error handling. Your code is fundamentally correct - but you can clean things up by checking for errors less frequently, or using a catch-all approach like teabot mentioned in his answer with NSException. A lot of the built-in functions that return errors (like NSFileManager's moveItemAtPath:) return a BOOL in addition to a providing an NSError object - so you could also use nested if statements if you don't need the NSError information.
All and all though, there's really not a great way to do this. If your code is long, KVO might be a cool solution. I've never tried it for a situation like this, though.
Note: When I posted this I was unaware of any MacOS/Cocoa exceptions debate. Please bear this in mind when you consider this answer.
Why not use exceptions instead? This will allow you to dispense with the error parameter on your methods and handle your errors in one place.
-(IBAction)buttonPress:(id)sender {
// Create Document Shopping List with this document
#try {
[self doSomething];
[self doSomethingElse];
[self doYetSomethingElse];
} #catch (NSException* e) {
[NSApp presentException:e];
}
return nil;
}
You will of course need to throw exceptions as required from within your doXXXX methods:
NSException* e = [NSException exceptionWithName:#"MyException"
reason:#"Something bad happened"
userInfo:nil];
#throw e;

I must enclose object creation/release with try/finally?

In Delphi, is normal do this:
ob = TObject.create;
try
//code
finally
ob.free;
end;
I wonder if that is similar in Obj-c.
You could do it that way, but exceptions tend to have a high cost in Objective-C. There are some differences in their performance between the 32-bit and 64-bit ABIs, as well as the interaction between Objective-C exceptions and C++ exceptions.
An alternative is to create your objects such that they are autoreleased and only retain them before your method ends.
SomeClass *object = [[[SomeClass alloc] init] autorelease];
/* deadly code here */
return [object retain];
This way even if your code experiences an exception your object will be released the next time the autorelease pool is drained (usually at the end of the event loop), assuming that the exception is not fatal and causes your program to crash.
Apple has some documentation about Obj-C exceptions
and the release notes for Leopard towards the end discuss the changes in the 64-bit ABI.
No. Objective-C does support exceptions and you see them in Cocoa infrequently (NSError is the direction Apple is headed) but you definitely wouldn't use them every time you initialize or release an object.
I'm certainly no expert in Obj-C but the fact that it provides (what people have asked in Delphi) the compound try/catch/finally, gives you the choice to use that to program defensively like in Delphi:
#try {
// protected block
}
#catch (id theException) {
// do smthing with theException
}
#finally {
// clean up code
}
And I would argue that if programmers used the #finally more often, there would be less bugs in their developments.
good answers, however...
I stand to be corrected, but it is my understanding that #try {} #finally {} is different in concept and therefore application to #try {} #catch {} #finally {}, in that if you don't raise any exceptions there is minimal overhead, however when exceptions are raised (which should be by definition, the "exception rather than the rule"), they serve to protect the resource being wrapped, leaving a #catch handler further up the food chain to deal with logic side of dealing with the exception.
as an example, here is a construct i often use when i have to return an autoreleased value that would autorealease a lot of extraneous data into the callers pool, if it were not for the #try/#finally/drain/autorelease construct you see here.
+(NSArray *) arrayOfUrlPrefixAssociatedUrlArraysFromUnsortedArrayOfUrlStrings:(NSArray *)urlStrings {
NSArray *arrayResult = nil;
NSAutoreleasePool *wader = [[NSAutoreleasePool alloc] init];
#try {
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (NSString *urlString in urlStrings) {
BOOL addedToPrior = NO;
for (NSString *prefix in result.allKeys) {
if ([urlString hasPrefix:prefix]) {
[(NSMutableArray *) [result objectForKey:prefix] addObject:urlString];
addedToPrior = YES;
break;
}
}
if (!addedToPrior) {
[result setObject:[NSMutableArray arrayWithObject:urlString] forKey:[self urlPrefixFromUrlString:urlString]];
}
}
arrayResult = [[NSArray alloc] initWithArray:[result allValues]];
}
#finally {
[wader drain];
}
return (arrayResult?[arrayResult autorelease]:nil);
}