Vincent Gable’s Blog

May 17, 2010

Don’t Check For nil in Your dealloc Methods

Filed under: Cocoa,Programming | , ,
― Vincent Gable on May 17, 2010

There’s no need to check if a variable is nil before release-ing it, because calling a method on a NULL variable is a no-op in Objective-C. And the runtime already has a super-fast check for this case.  So adding an extra if test into your code will probably slow things down.

Doing a pointless ” ==?nil”  test is bad for two reasons.

Firstly, it’s more code for no good reason. Even if it’s just one more line, It’s one more line to debug and test. It’s one more place where something could go wrong.

Secondly, it’s not idiomatic Cocoa-code, so it signals that something strange is going on. That’s a problem for whoever is reading the code, because they have to stop and look around more carefully to figure out why the pointless tests are happening.

In summary, do NOT do this:

– (void)dealloc;

{

if(baseImage) {

[baseImage release];

baseImage = nil;

}

[super dealloc];

}?

Do this:

– (void)dealloc;

{

[baseImage release];

baseImage = nil;

[super dealloc];

}

April 29, 2010

What Am I About To Call?

Filed under: Cocoa,iPhone,MacOSX,Objective-C,Programming,Reverse Engineering,Tips | , ,
― Vincent Gable on April 29, 2010

Say you’re in gdb, and about to execute a call instruction for dyld_stub_objc_msgSend, how do you know what’s about to happen?

On i386

(gdb) x/s *(SEL*)($esp+4)

tells you the message that’s about to be sent.

(gdb) po *(id*)$esp

tells you the target object that’s about to get the message.

March 23, 2010

Cocoa Influenced The Gang of Four

Filed under: Cocoa,Design,Objective-C,Programming,Quotes | ,
― Vincent Gable on March 23, 2010

Next time you want to gloat about how seminal Cocoa is,

Erich Gamma: Yes, and it is funny that you mention the iPhone. The iPhone SDK is based on the NeXTStep object-oriented frameworks like the AppKit. It already existed when we wrote Design Patterns 15 years ago and was one source of inspiration. We actually refer to this framework in several of our patterns: Adapter, Bridge, Proxy, and Chain of Responsibility.

Richard: Which is a great example of the enduring nature of good design, and how it survives different technical manifestations.

Erich: Just as an aside, it is also easy to forget that we wrote design patterns before there was Java or C#.

Source: Design Patterns 15 Years Later: An Interview with Erich Gamma, Richard Helm, and Ralph Johnson

December 25, 2009

A C &Puzzler[]

Filed under: Announcement,Bug Bite,C++,Objective-C,Programming | , , ,
― Vincent Gable on December 25, 2009

Here’s a C-puzzler for you!

given this function,

void foo(char* s){
	printf("s is at: %p\n s is: '%s'\n", s, s);
}

and that

char s[] = "Joy!";
foo(s);

prints out

s is at: 0xbffff46b
s is: ‘Joy!’

what will this next line print?

foo(&s); //WHAT WILL THIS DO?

Pick all that apply:

  1. Print “Joy!”
  2. Print garbage
  3. Print the same address for s
  4. Print the a different address for s
  5. Crash
  6. Go into an Infinite loop

Answer

Answer: one and three

Yeah, it’s not what I expected either, especially since:

@encode(__typeof__(s)) = [5c]
@encode(__typeof__(&s)) = ^[5c]

In fact, all of these are equvalent (modulo type warnings):

foo(s);
foo(&s[0]);
foo(&(*s));
foo(&s);

Explanation.

December 9, 2009

Compile Safer

Filed under: Bug Bite,C++,Cocoa,iPhone,MacOSX,Objective-C,Programming | , , ,
― Vincent Gable on December 9, 2009

Peter Hosey explains what warnings he uses and why. It’s good, but long. Fortunately, you can just grab a script, and enable those warnings in your Xcode projects.

Warnings = Errors

If I could force just one compiler flag on everyone who’s code I use, it would be TREAT_WARNINGS_AS_ERRORS. As a rule, things don’t get improved if they aren’t broken. (How many times have you said “I’ll come back and fix this code later”? Yeah.) Warnings fester and grow on each other, until they cause a real breakage. It’s an inescapable evil of building software with finite resources.

If a warning isn’t worth stopping the build over — it’s not worth checking for in the first place.

Use the Latest Tools

Specifically, if you aren’t using Snow Leopard and Xcode 3.2 to build your Objective-C code, you are crazy. Trust me, painless static analysis is worth upgrading for. It catches maddening memory leaks, not just trivial type errors, like adding an int to an NSArray, that you would catch immediately.

December 7, 2009

Dot Syntax Solution

Filed under: Cocoa,Design,Objective-C,Programming,Usability | , , , ,
― Vincent Gable on December 7, 2009

Surprisingly, the addition of dot syntax to Objective-C 2.0 has been a major source of controversy. I wonder if there’s some kind of Bike Shed effect at work here: the problem dot-syntax causes is trivial1; while the clarity it brings to code is minor. So it essentially boils down to aesthetics. (For the record, I like the dot, even with it’s current flaws, but I don’t believe it’s worth fighting for).

The Actual Problem

The problem is that when you see a.b = c; you don’t know if it’s:

  1. Assigning the b field of a struct to c. This basically compiles down to one move instruction.
  2. Invoking the -setB: method on an Objective-C object. By convention -setB: should update the b property of the object to hold the value c, and nothing else. But it might have side effects, or be really slow.

A Solution

Using a different symbol to access Objective-C properties would remove all ambiguity. Nobody would mistake a@b = c; as assigning to a C-struct. It’s clearly an Objective-C construct.

But personally, I’m not a big fan of the @ character. It’s ugly; it’s noisy; there’re just too many lines in it. I think U+25B8 ‘BLACK RIGHT-POINTING SMALL TRIANGLE’ would make a better choice,

obj▸property = value;

And since ‘▸’ can’t be part of a valid C identifier, you can basically preprocess your code with s/▸/./, then compile it with existing tools.

Of course, it doesn’t matter what character(s) is picked, so long as it’s clearly different from existing C syntax; and you have a way of replacing it with a . before building it.

1 I’ve heard experienced developers complain that dot-syntax = a steeper learning curve for newbies, and that it can be confusing, but I haven’t actually seen one come out and say ‘I spent X hours debugging a problem that I couldn’t see because of it’. The fact is, any situation that dot-syntax would obscure is already pathological. In the end I just can’t see dot-syntax mattering much.

October 19, 2009

sizeof() Style

Filed under: Bug Bite,C++,Objective-C,Programming,Tips | , ,
― Vincent Gable on October 19, 2009

Never say sizeof(sometype) when you can say sizeof(a_variable). The latter works even if the type of a_variable changes, and it is much more obvious what the size is supposed to represent.

October 12, 2009

Don’t Check malloc()

Filed under: C++,Cocoa,iPhone,MacOSX,Objective-C,Programming,Quotes,Tips | , , ,
― Vincent Gable on October 12, 2009

There’s no point in trying to recover from a malloc failure on OS X, because by the time you detect the failure and try to recover, your process is likely to already be doomed. There’s no need to do your own logging, because malloc itself does a good job of that. And finally there’s no real need to even explicitly abort, because any malloc failure is virtually guaranteed to result in an instantaneous crash with a good stack trace.

Mike Ash

This is excellent advice. Peppering your code with if statements harms readability and simplicity.

It’s still a good idea to check large (many MB) mallocs, but I can’t imagine recovering gracefully from a situation where 32 byte memory allocations are failing on a modern desktop.

September 11, 2009

Never Start An Integer With 0

When programming, never start an integer with 0. Most programming languages treat a decimal number that starts with 0 as octal (base-8). So x = 013; does not set x to 13. Instead x is 11, because 013 is interpreted as 138 not 1310.

Languages with this quirk include: C, C++, Objective-C, Java, JavaScript, Perl, Python 3.0, and Ruby. If you add up the “market share” of these languages, it comes out to above 50%, which is why I say most languages.

“But I use {Smalltalk, Haskell, Lisp, etc.}”

I’m jealous that you get to use such a nice language. However, it’s bad programming hygiene to pick up habits that are dangerous in common languages.

Now, I assume you wouldn’t write 7 as 007, unless the leading zero(s) carried some extra meaning. There are cases where this clarity outweighs “cleanliness” (unless the code meant to be ported to a C-like language).

But you should at least be aware of this inter-lingual gotcha.

June 15, 2009

Ignoring Just One Deprecated Warning

Switching projects over to iPhone OS 3.0 means discovering that functions I’m using are deprecated. Occasionally there isn’t a totally straightforward replacement, and the best thing to do is to file a bug/TODO/note for myself, and ignore the warning until a later version, when major refactoring will be possible. But bitter experience has taught me to have Xcode treat warnings as errors1, so it’s necessary to trick the compiler into ignoring the warning for things to build.

-Wno-deprecated

The -Wno-deprecated flag tells GCC to suppress warnings about deprecated code. But adding it to an Xcode project means you won’t get useful warnings about other depreciated code.

You could file a bug telling yourself to turn that warning back on after the deprecated functionality has been updated. That should work just fine. But it feels like bad project hygiene to me.

Casting and Protocols

Type casting is a dangerous old-C technique that’s earned its infamy. But it’s undeniably fitting to use a deprecated language feature to get deprecated code to build. The basic idea is to declare a protocol that includes the method you want to suppress warnings for,

@protocol DeprecatedHack
- (void) myDeprecatedMethod;
@end

then just cast your objects so the compiler thinks they implement the protocol,

[foo myDeprecatedMethod]; //warnings
[(id<DeprecatedHack>>)foo myDeprecatedMethod]; //no warnings

Although having to declare a protocol is somewhat heavyweight, it leaves a nice artifact in the code reminding you to replace deprecated functionality.

Protocols Not Required

Sometimes just casting to id is enough. This happens if another object has a non-deprecated method with the same name.

1For experimental or prototyping projects I let warnings slide. But in the main project I always treat warnings as errors. Ignoring them in production code has never worked — warnings fester and grow on each other.

Because Objective-C is so dynamic, there are many errors that the compiler can warn you about, but can’t be totally sure are errors. For example, methods can be added to a class at runtime, so if you call -someMethodThatDoesNotExistAnywhere, the compiler will warn you that something is up, but won’t stop the build, because the necessary code could magically appear at runtime. Of course, 99% of the time, it’s me accidentally using count when I meant length, etc. What I’m really trying to say here is that treating warnings as errors is an even better idea in Objective-C.

« Newer PostsOlder Posts »

Powered by WordPress