a glob of nerdishness

September 18, 2009

Grand Central Dispatch

written by natevw @ 12:55 pm

Mike Ash just finished another accurate and detailed series covering an interesting low-level topic, this time explaining all about Grand Central Dispatch.

Apple’s thread pools help reduce processor contention, but I’d been mulling over how to best use queues for performing file operations optimally. Mike nails it in this last post: create a hierarchy of custom queues that end up funneling operations through one custom queue per disk. It’d be interesting to wrap this technique in a higher-level API that dealt with disk and other bottlenecks in a more automatic manner.

January 6, 2009

Exceptions versus NSError

written by natevw @ 10:07 pm

Michael J. Tsai:

“NSError, ugly though it is, actually seems to be a pretty good system for managing and propagating errors generated by different layers of code and even different languages.”

When I first read that, I was taken aback. The way Cocoa uses NSError is almost exactly like exceptions, but with no language support. Instead of getting a return value OR an exception when calling a function, you need to declare storage for both the return value AND the error. With NSError, the return value must also be of a type with “room” for an invalid flag, like a pointer that can be nil or a “succeeded” boolean that can be false. As if the lack of tuples in C wasn’t occasionally frustrating enough, now even many structures must be returned by reference rather than value just because they weren’t able to convey the “failed, check error” message. Even generating an NSError is a pain, and handing a lower one up the stack isn’t much more fun.

But in the end I think Michael is right. In pure C++, where idiomatic code leads to the stack itself doing most of the memory management, exceptions are great. I’d expect similar benefits in completely garbage collected languages as well. Cocoa on the other hand is such a mixed bag: reference counting with varying amounts of autorelease, or garbage collected; with C API usage encouraged, C++ contamination allowed (and fairly well supported as of Leopard). Then factor in the growing trend of bridging Cocoa into other languages. Having to bubble up errors through an ugly old explicit error mechanism starts to look a bit more appealing.

June 16, 2007

Global C++ Exception Handling

written by natevw @ 12:01 pm

It’s easy to handle uncaught exceptions at a global level in a C++ program. Most compilers, if not all, provide a function called std::set_terminate(). This lets you register a function that gets called when the program terminates unexpectedly due to an error. This function does not take any arguments, but can re-throw any current exception:


void catch_global() {
 try {
  throw;
 }
 catch (const YourPrintableException& e) {
  std::cerr << "Exiting due to error: " << e << std::endl;
 }
 catch (...) {
  std::cerr << "XQI ERROR -42: UNEXPECTED OCCURRENCE" << std::endl;
 }
 abort();
}

int main() {
 std::set_terminate(catch_global);
 if (true) throw "up";
 else return 0;
}

While this shouldn't replace good error handling practices throughout your code, it can be a handy way for your program to put some last words on the record before it kicks the bucket.

One disclaimer: I'm not completely sure that set_terminate() is an official part of the C++ standard. It's in Thinking in C++ but not the C++ FAQ-Lite, the big C++ reference or the light C++ reference. Official standard or not, it seems to be widespread. You can find documentation on set_terminate() via GNU, IBM or MSDN.

May 12, 2007

Subtle bugs stink

written by natevw @ 7:20 am

Consider the following piece of code, to process hex color strings:
sscanf(text, “#%2x%2x%2x%2x”, &rgbcolor.r, &rgbcolor.g, &rgbcolor.b, &rgbcolor.a);

Looks pretty standard, eh? Well, that piece of code cost a day’s work. I was getting segmentation faults in std::list’s iterator post-increment. The iterator had no clear reason to be invalid, although the debugger did show bad values (0×0 or 0xbf000000 for the _M_node internal pointer it was trying to dereference). I copied my project, and hacked it down to a smaller main code path. Strangely enough, the presence the constructor for an otherwise unused class was the shibboleth that determined whether my code crashed or not. Suspecting a compiler bug (how pride resists being wounded!), I tried all manner of settings (optimization, static vs. dynamic linking) before I finally went back to said constructor. Lo and behold, when the constructor called a code path that involved the sscanf above, std::list exploded. When not, it was fine. What on earth?

Well kids, this is why C-style formatters are considered harmful. Sure I had four %x’s and four variables, but “%x”es expect ‘int’ and my variables happened to be ‘char’s underneath a typedef. So the problem was not in std::list, not in the derived class, not in my main code and not even directly in the constructor that clued me in.

Using C++ stringstreams can be a pain, but so is debugging things like this. I wonder if that’s why C++ often gets a bum rap.

January 13, 2007

C programmer whoa/duh moment

written by natevw @ 10:03 am

While searching for info on how the “ISA Reference” item came to be in my application services menu, I came across a fantastic post on a blog which just got added to the sidebar: Generating Machine Code at Runtime. Esentially, you store machine code in an array (anyone remember POKE in the good old days?) and call the pointer as a function. I was stunned, and then shamed. What else is a function pointer if not a pointer to machine code in memory?