You are currently browsing the category archive for the ‘Error Handling’ category.

How many times have you ever legitimately used the comma operator in live C or C++ code? I’ve seen a Boost project use it as convenience notation for small compile-time datasets, but that’s about it. So, here’s an example of an absolutely terrible way to use it (yes… this is how I blow off steam at work):

wtf.c

#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
    return argc > 1 ? !strcmp(argv[1], "foo") ? \
        (puts("foo"),0) : (puts("not foo"),1) : 1;
}

This program prints “foo”, “not foo”, or nothing based on the first argument; then it returns true (UNIX-style) only if the first argument was “foo”. While most language experts will not bat an eye at this, it’s definitely on the Perl side of ugly.

operator, in action

Why was I playing with the comma operator? I was looking at the definition of assert() provided on my system (either part of libc or gcc, I’m not sure). If you disable assertions (-DNDEBUG) you’ll see a null statement like this:

test.c

#include <assert.h>
void test(int x, int y)
{
    assert(x < y);
}

gcc test.c -E -DNDEBUG

void test(int x, int y)
{
    ((void)(0));
}

If you leave assertions enabled, however, you’ll still see a null statement due to the somewhat-creepy comma-operator magic I’ve demonstrated above:

gcc test.c -E

void test(int x, int y)
{
    ((void)((x < y) ? 0 : \
        (__assert_fail("x < y", "test.c", 4, "test"), 0)));
}

So, assert is defined as an expression rather than a statement. That means that you can combine it with other chunks of code in some surprising fashions:

char *short_strdup(const char *str, size_t len)
{
    // don't allow anyone to pass in a null or over-long string
    return assert(str != NULL), assert(strlen(str) < len), strdup(str);
}

long infallible_atoi(const char *number)
{
    char *end;
    long value = strtol(number, &end, 10);
    // validate that there was no conversion error
    //          and that we consumed all input
    return assert(errno == 0), assert(*end == '\0'), value;
}

This is not recommended, however, because assert is not a general-purpose error-handling mechanism. I could imagine this being used as the basis for a hand-rolled assertion mechanisms in a large codebase (you could throw an exception, log an error with a stack trace, or cause monkeys to fly out of the original developer’s nose, for example).

Advertisements

I was originally going to write my thoughts about exceptions vs. error codes in the context of PHP development, but I got completely sidetracked. So instead, I’m going to talk a little bit about Java. Please remember that I have written a grand total of about 30 lines of Java code in the last 5 years, and I could very well be talking out of my ass. But I like to think I’m not an idiot, even if I’m not fluent in the language.

There’s a particular API wart I’ve seen with Java file I/O. I can’t find any references right now (sorry!), but I’ve seen it mentioned in the context of Java, RAII (which Java doesn’t have, yet some people do argue to that effect), checked exceptions, and general error-recovery strategies.

This (pseudocode) is the core of what you have to do when you open a single file in Java:

void doFileIO() {
  File file;
  try {
    file = new File(path);
    // do stuff with file
  }
  finally {
    try {
      file.close();
    }
    catch (IOException e) {
      // couldn't close the file... but why? and do we care?
    }
  }
  return;
}

Why is that so ugly? Read the rest of this entry »