Archive for category Solid Coding

Preventing a goto fail (part 2)

I’ve been interviewing candidates lately, which has made me think about everyday things in terms of screening/interviewing questions. Perhaps then a good question for an iOS developer is “How would you prevent a goto-fail situation?”.

Of course, “braces” comes up first, and compiler options may come up second, so let’s change that to “Aside from braces and compiler settings, how would you prevent a goto-fail situation?”.

Over the last few days, I’ve been reversing my role to think how I would answer that from an interviewer.  The idea that occurs to me the most boils down to “defensive coding” or “best practices and standards”. Now that’s way too vague.  As an interviewer I would ask for details.  I’m sure any practiced interviewer would.

For me, the biggest problem with the goto-fail code is the assumption of success until failure throughout the instructions. In critical code, it is better to assume failure until success is specifically reached.  Read the rest of this entry »

Preventing a goto fail

There was an embarrassing coding moment in developer news recently.  When I think about how easy it is to make similar mistakes, I starting thinking like Steve Maguire in his book “Writing Solid Code”.  How could this problem have been detected or prevented? (And I’m not debating the use of GOTO’s. Someone else can do that.)

I first heard Steve Gibson describe the code on “Security Now!” podcast episode #444 (show notes). How would the compiler detect that? After I got back to a computer where I could look at it, I saw the writeup at Adam Langley’s ImperialViolet blog. Adam discussed things like how the consistent use of braces might have made it more obvious.  But Solid Coding principles stress automatic ways to detect problems, so I was happy to see Adam’s note about the -Wunreachable-code option of the Clang compiler. That might have detected code being disabled by the GOTO, but as Adam also pointed out, it is not one of the options included in -Wall option.

Adam didn’t go into what the option would reveal, so I created a quick command-line tool from templates in Xcode. Compiling with the default options failed to note the problem. Adding -Wall did not detect the problem.

But when I added -Wunreachable-code to the “Other Warning Flags”

Xcode-both-warnings-smaller

Xcode finally found the problem.  (Note that I had “Treat Warnings As Errors” set to YES.)

DeadCodeWarning4-crop-small2

 

So, adding the -Wunreachable-code compiler warning is the lesson of the day.   I’ll be looking into it for my project tomorrow.

 

 

 

Tags: , , ,

Solid Coding: Autoresize Masks

UITableView cell contains UILabel set with mask to pin the left and right and allow change to width

If the frame of the cell shrinks past the origin of the UILabel, then the right side of the label will be beyond the right side of the cell frame when it was previously contained entirely inside the frame.

This can be detected with Assertions in the ‘setFrame’ method or you can override the incoming frame to prevent the cell’s frame from shrinking so small that the expansion will be incorrect.

Favorite Quotes 6

“The only thing you can safely assume is that it is unsafe to assume anything.” – Walt Sellers

I recently wrote this while discussing things with a colleague.  Eric Rodriguez-Diaz long ago taught me to challenge my assumptions. I now believe that bad assumptions are a large part of most of the bugs in code.

Tags: ,

IDE Feature Wish List – Comments in Project File

More things for the IDE (Integrated Development Environment).  Xcode is the one I use for iPhone development,  so hint, hint Apple.

Provide space to comment settings provided to the compiler by the IDE.

We can specify compiler macros and such in lots of IDEs. One example is a preprocessor flag named “DEBUG”.  Yet there may be definitions for preprocessor macros that do not explain themselves.  A deliberately bad example may be  “MAKEOBSCUREOPERATIONSALLOWED”.

If there is a place in your work where you as “why did someone do that?” then you have a need for more information.  And that information should travel with the thing it describes, not in some separate file where it may be lost (or never found).

If there is a slot to make a decision (especially a decision for another file), then there needs to be a slot to record the reason for the decision.

Tags: ,

Solid Code: Mixing Objective-C and C++

If you’ve noticed that there’s been a long time between this post and the previous one,  you are right. My day job has been keeping me busy.  But that’s why I can get on with the topic: mixing legacy C++ with Objective-C.

After trying things a few ways,  I’m finding that one basic assumption difference between the languages can trip you up: the assumption about calling a method or function with an object pointer to zero (a.k.a. nil or null or NULL).

Since the C++ will generally be legacy code,  its natural for Objective-C objects to wind up containing pointers to C++ objects.  After that, its pretty easy to wind up calling C++ functions almost directly from accessors like:

This is functional,  but from a solid-coding standpoint,  it is too bug-prone and too hard to debug.  If the above statement crashes, which part of it failed?

Objective-C assumes that calling member methods with nil object pointers is OK.    (i.e., a nil ‘self’ pointer is not an error.)  Any such attempt just automatically returns zero.

C++ however, assumes that member functions will never be called against a NULL pointer.  (i.e., a NULL ‘this’ pointer.)  Any such attempt will probably crash an iPhone with EXC_BAD_ACCESS.

My point here is you should put the pointer into a variable, then call the function from that variable:

Now the language assumptions are clearly separated.  Nil pointers in the first line can be safely assumed to have zero method results. And the C++ in the second line can be more easily debugged if it fails.  (And we can easily check our C++ pointer for NULL before calling its function.)

The crash from the C++ code will most likely happen when the member function tries to dereference a member variable.  An instance’s member variable is held at an offset from the pointer, so if the pointer is zero, the member equates to an address that is near zero.  Addresses near zero are invalid on the iOS.

So there you go,  if you have to mix Objective-C and C++,  avoid mixing them on the same line.

Tags: , , , ,

Back To Basics of Solid Code

One of my all-time favorite industry books is “Writing Solid Code” by Steve Maguire. (As you may already know.) The principles spelled out in the book are timeless, even if the implementation examples are getting old.

I’ve been using iOS environment variables to implement some automatic tests for memory issues for a while:

  • NSZombiesEnabled
  • MallocStackLogging
  • MallocStackLoggingNoCompact

The first is a big help for getting the system to tell you when you are trying to use pointers to Objective-C objects that have already been freed. The other two help find where in code a pointer was freed. They’ve been such a help that I leave them on full-time.

Yesterday I started using some of the other environment variables available. These can be a big help for finding memory management issues in your C and C++ code (legacy or not.)

These are very good for executing the Solid Coding principle “Fortify Your Sub-Systems”. Or, as I prefer to think of it, “shred your garbage”. Basically, Apple fortified the allocation subsystem for you.

  • MallocScribble – causes system allocation functions to write 0x55 over all freed memory blocks.
  • MallocPreScribble – causes system allocation functions to write 0xAA over all new allocated memory blocks before returning them.

About an hour after turning these on, I had my first hit on a dangling pointer. A pointer that was an instance member of a C++ object was set to 0x55555555 after the object had been freed. Trying to dereference it threw the EXC_BAD_ACCESS exception and dropped me into the debugger. (See my post on how to make execution stop at the beginning of an exception.)

A “random” crash is now not random and found.