Monday, March 5, 2007

Free Noob Lesson #2

We've all done this-

- (id)init
{
if (!(self = [super init]))
return nil;

// etc.
}


That obviously returns nil when [super init] fails.

But what if you accidentally add(or forget to remove) an extra semicolon?

- (id)init
{
if (!(self = [super init]));
return nil;

// etc.
}


GCC is perfectly happy with that, but your application is not. The above code reduces to this useless logic:

- (id)init
{
self = [super init];

return nil;
}


One might say that we could avoid this by returning self instead of nil, but then the code in 'etc.' would still never be executed, and the resulting bug would probably be much harder to locate.

The only quick and easy protection that I can think of is sobriety, which is clearly out of the question. Any thoughts?

6 comments:

Karsten said...

i usually stick to this:

if (self = [super init])
{
//init code
}
return self;

i think this should also work with the ; in place, unless you use some wicket stuff with [[self doSomething] doEvenMore].

Karsten

lee said...

do this....

[super init];
...
return self;

lee said...

i meant to say "I do this...."

:-)

Peter Hosey said...

I do what karsten suggested, though I have an extra layer of () so that I can use the GCC warning for unintentional assignment (extra parentheses tell GCC that it was intentional).

But if you really want to stay with the separate assignment and test, have your editor color semicolons in a bright, highly-noticeable color.

Blake C. said...

While Mr. Shipley would be pleased with lee's idea, I think I'll be using Peter's version in future. While I usually fight the tyranny of indentation tooth and nail, it serves a good purpose in this case.

Thanks, all!

Anonymous said...

gcc has a generic C/C++/ObjC warning for this. Should enabled with -W, or maybe -Wall -Wextra or possibly something else, since they change things version to version.