Older blog entries for pphaneuf (starting at number 325)

15 Oct 2007 (updated 15 Oct 2007 at 15:07 UTC) »

Assertions and Exceptions

[info] wlach wrote an excellent article recently on how to use (and not use!) assertions properly, and it reminded me of some of my reflections on assertions and exceptions (warning: this is mostly written with C++ in mind, which does not have checked exceptions, no matter what you may think).

I would first like to emphatically support his first point: taking out an assert or turning it into a warning is not a "fix". A good developer will do a root cause analysis and find out why the pre-condition was being violated, since that is the real bug. I remember, a very long time ago, running GTK+ and GNOME programs from the command-line, seeing so-called "assertions" scroll past by the dozen, and thinking "oh my goodness, we are so doomed". I don't think Qt/KDE was much better either, but it's been a long time, and that's what I used to use. Now I start things from the menu, and I'm blissfully ignorant of how close to the cliff I'm dancing...

I used to despise exceptions, finding that they obscured the code path and made difficult the task of tracing through what is really happening in your code. It also forced me to litter my code with try/catch blocks, because as soon as you turn on exceptions (or rather, don't turn them off), anything can go wrong, at any time. What I learned later is two-fold.

First, like most tools (and C++ is very "good" at this, giving us very sharp, but dangerous tools!), exceptions can be abused, and most of the early code using exceptions that I met probably suffered a bit from the novelty aspect (it was a "sexy thing" back then, I guess), and over-used them massively. The second assertion mistake
[info] wlach talks about, using assertions for errors that may occur in the course of normal (or "non exceptional", if you will) program execution, applies to exceptions as well.

My current opinion is that functions that use exceptions to signal errors should also have a non-throwing alternative, for the cases where you do expect it. One example would be a string to integer conversion. Another can be taken from Boost, where there is two ways to convert a weak_ptr to a shared_ptr, an implicit way that throws and an explicit way that doesn't (but could give you a "null" shared_ptr and has to be checked for). The latter one is especially good design, since the "safer" exception throwing version is also the more implicit, "shoot from the hip" version, nicely counter-balancing each others.

Second, your code has to be exception safe. What this means is that getting an exception should not leave things in a bad state. Back in the days, we used raw pointers a whole lot, because this was how it was done, so basically any time that memory was allocated on the heap, you'd have had to wrap it in a try/catch block, so that if an exception happened, you'd free the memory on the way out. This was rather tedious, to say the least, and when you look back on it today, so was using raw pointers (and having to free memory manually). Nowadays, smart pointers rule the land, and it is incredibly easy to write exception-safe code with nary a try/catch block in sight, all appropriate cleanup being stowed out of sight in destructors.

So, exceptions, not so evil after all, but still should be used for exceptional conditions (big surprise!). But with the latter point, I was seeing a strong parallel with assertions, and in particular, those that I never want disabled. Now, think about it for a moment about what happens with unhandled exceptions: they call abort(), after writing a short message that tries to say what happened, just like an assertion. And defining NDEBUG doesn't touch the throws. That's exactly what I was looking for!

Not only that, but I now see many things that we did in WvStreams that have similar or better equivalents. For example, we added a crash dump and a "last will" feature. The former produced a text file (in addition to a potential core dump) when crashing, with a textual stack trace. The latter was a function you could call to set a string to be put in the crash dump in case something happened, to explain what was happening at that moment. GCC's default terminate handler manages to get at the exception object, so I guess it should be possible to do the same and put the information in the crash dump (this would be platform-dependent, but getting the stack trace already is, so this is not a big deal). The "last will" could also be implemented more efficiently by using a try/catch block and giving the "last will" information only in the case of an exception (making the non-exceptional path fast and quick, only having extra work in case it is really needed), then re-throwing (this is called "exception tagging", if I'm not mistaken). Note: as I mention to [info] sfllaw in the comments, the "last will" cannot be replaced by a try/catch block, because some crashes are not through exceptions (segmentation faults, for example).

Also, in the event-driven multiplexing servers that WvStreams is usually used for, it's quite possible that an exception was only fatal to a single connection, and this gives the program the possibility of choosing a middle-ground between just logging a warning or dying altogether: it can now kill off the offending connection, log that event, and keep on going.

I still use assert(), but only for the more troubling things, such as detecting stack or heap corruption, where the only sane thing to do is really to abort the whole program. This is the kind of thing that is so exceptional that if someone disables it with NDEBUG, it wouldn't be the end of the world. I can put more expensive checks (such as canaries and magic cookies) that get disabled with NDEBUG, and at worst, leave a few "if (...) std::terminate();"

Finally, one thing that has long annoyed me were objects that have a method to know if the constructor had a problem, and where if it did, the object is invalid. Forgetting to check this state is a common source of bugs (especially in cases where the object is just instantiated on the stack), and this can often make the rest of the object's implementation more complex, having to check for validity on every method. Note that this validity check often should be an assert, IMHO.

Now, why carry this extra state all the time? This is an exceptional condition, adding an extra code path over the whole lifetime of your object, based on a single boolean value which will be set to the "valid" state 99.9% of the time, thus making sure that there's only a 0.1% chance alternative code path, you can picture what will be the test coverage of that! Exceptional condition, asserting on it, assertions should often be exceptions, hmm... Why not just tackle this at the source? Throw an exception in the constructor when the object would be invalid. The C++ runtime will free the memory, if it was heap-allocated. You'll have to be careful at object instantiation time, but you'd have to be anyway (checking the validity or wrapping in a try/catch block, pretty much the same overhead). If you ever forget, your program will still be correct, and will terminate, the exact same behaviour as if you didn't check the validity and called a method! Isn't that elegant or what?

The net footprint of that is a simpler implementation with fewer code paths to test, and zero real additional code for the user (the validity check is replaced with a try/catch)!

That's what convinced me that exceptions weren't so evil, when I found this case where they reversed the trend and gave me simpler code to understand than without exceptions, and that was more robust to boot. The try/catch block was perfectly unobtrusive, and in my simple test programs where I didn't care and would have let it assert(), it did too, but at the exact place where the object was deemed invalid (with more context to see why), instead of randomly later.

So, don't go forward and assert, but rather, go forward and throw!

Syndicated 2007-10-15 11:38:57 (Updated 2007-10-15 14:19:53) from Pierre Phaneuf

By the way...

Wow, I'm quite busy these days, haven't been writing (or reading, for that matter!) much...

Mostly, it's to blame on the quest for a place to live in that's going on. I'd like to buy, this time around, so this makes it a couple of notches more complicated than what I'm used to (I've never been an owner, so this is all new to me). The numbers bandied around are making me quite dizzy! Hopefully, we should come out of this with a nice place, but in the meantime, it's time for "let's save up money like crazy for the cash down", so on top of being busy with this stuff, it'll also make me less visible than I usually am (well, uh, it should still be better than the last year!).

In other more geeky news, I think I am succumbing to the coding style of the C++ standard library with regard to naming. For method names, there's more than a few people who are going to think "finally!" (I used to favour a Java-style interCap, like "readUntil", now I tend to prefer "read_until"). This makes a lot of sense, since this is also more common in C and Perl code. But the more controversial part is that the standard library uses all lowercase for class names (it's "unordered_set", not "UnorderedSet"), and I'm getting a crush on those too... Perl, Ruby and Python are using FullyCapitalized style for those, and so are a number of C++ programmers I know, but I'm finding that there is something to be said for adopting the style of the language. I'm also using namespaces and exceptions (mostly in constructors and object-returning methods) more, these days.

So either I'm becoming stylish, or I'm becoming senile. Oh well.

Also, it would seem that the giant jackhammers are following me.

Syndicated 2007-08-24 15:14:07 from Pierre Phaneuf's Diary

By the way...

Wow, I'm quite busy these days, haven't been writing (or reading, for that matter!) much...

Mostly, it's to blame on the quest for a place to live in that's going on. I'd like to buy, this time around, so this makes it a couple of notches more complicated than what I'm used to (I've never been an owner, so this is all new to me). The numbers bandied around are making me quite dizzy! Hopefully, we should come out of this with a nice place, but in the meantime, it's time for "let's save up money like crazy for the cash down", so on top of being busy with this stuff, it'll also make me less visible than I usually am (well, uh, it should still be better than the last year!).

In other more geeky news, I think I am succumbing to the coding style of the C++ standard library with regard to naming. For method names, there's more than a few people who are going to think "finally!" (I used to favour a Java-style interCap, like "readUntil", now I tend to prefer "read_until"). This makes a lot of sense, since this is also more common in C and Perl code. But the more controversial part is that the standard library uses all lowercase for class names (it's "unordered_set", not "UnorderedSet"), and I'm getting a crush on those too... Perl, Ruby and Python are using FullyCapitalized style for those, and so are a number of C++ programmers I know, but I'm finding that there is something to be said for adopting the style of the language. I'm also using namespaces and exceptions (mostly in constructors and object-returning methods) more, these days.

So either I'm becoming stylish, or I'm becoming senile. Oh well.

Also, it would seem that the giant jackhammers are following me.

Syndicated 2007-08-24 14:58:03 (Updated 2007-08-24 15:14:07) from Pierre Phaneuf

I'm now jobful

Seems like I'm now a senior something-or-other at Cypra Media, which did cause me a bit of grief. It's a "targeted marketing" company, meaning at the moment that they'll be sending out emails with ads in them to people who, weirdly enough, asked for it.

I would have liked maybe a bit more "completely new and different" maybe, and while they seem open-minded, they're not quite an actual free/open source software company, merely using a lot of it. But C++ and Perl are two of my favourites at the moment (mostly for their ratio of how much I can bend them to my will to how much they suck), and I think I might be in for learning some AJAXy JavaScript hackery in the process, which I've been meaning to do for a while, so that's that. They're Scrum fans there, which is better than being, say, RUP! Still, I'm more of a chaos model type of person, myself. We'll see, I want to try Scrum first, as it doesn't look completely nuts.

So I'll be starting there as soon as tomorrow!

Syndicated 2007-08-02 03:18:43 from Pierre Phaneuf

Installers

I was reading What's Wrong With Setup.exe?, and so was Avery, apparently.

I pretty much agree with Avery (and commented so on Jeff's blog), but I'd like to comment on how tricky the part about the DMG files is. The problem is that Mac OS X bundles aren't a single file (that could therefore be downloaded "just like that" and would be very intuitive), but is really a directory full of files (that thus can't be fetched off a web server as a single unit).

I guess Apple was focusing more on the shrink-wrap software publisher's point of view (normally shipping an actual CD-ROM), and kind of provided a virtual equivalent, but it does feel a bit weird.

One solution could be to ZIP the bundle, and give the operating system the ability to run them directly. You could then just download an application, and run it, no weird installation, nothing. It'd be a challenge, for sure. For example, the fault handler in the kernel would have to be able to find the page inside of a compressed ZIP file, if you "do it right". You could cheat and decompress it silently, but that'd could make launching a big application with lots of resources very slow, which is exactly what using a bundle is supposed to help with in the first place (by demand-loading resources). I know about the "stuff the resources inside the EXE" trick, but bundles can (and often do) have multiple binaries.

But they could certainly bite the bullet and find a way, I'm sure.

Note that the Apple approach also follows Avery's first advice. Preference files are created as they are needed, while running the application. It also means that a system administrator can simply put up a read-only file share on the network with the applications used in the office, and it'll Just Work (tm).

Syndicated 2007-07-26 19:23:46 from Pierre Phaneuf

I'm a B-person.

Denmark, which I sometimes refer to as "the place the future comes from", gave me another reason to do so: the B-society.

Having just spent a year working a more or less 9-to-6 shift (we had "flex time" inasmuch we could arrive between 8:00 and 9:30), there's no doubt about it (if there ever was!), I'm a B-person.

One of the problem with being a B-person is the clash with the rest of society. Even if work lets me come in and do my hours whenever I want, there's shops, restaurants, and such. Having dinner at almost midnight can restrict choice a little bit, obviously! Social life can also be tricky. Although these is a natural clumping effect between people living similar lifestyles, they might not have as flexible work schedule. And I wouldn't even think of what things would be like with children! Ask anyone who's had to wake me up early in the morning...

But it would seems they're actually trying to tackle the issues, even having B-classes in school that start a few hours later. Just like the French had rules preventing abuse by employers asking employees to work later hours, they're picking up on the fact that, for some people it's asking them to not work later hours that is abuse. And that's the future.

P.S.: Also, in the same line of thought, why the 9 to 5 office worker will become a thing of the past. Not that it matters that much to me now, but I am curious to see how France will integrate that into its culture.

Syndicated 2007-07-13 18:43:27 (Updated 2007-07-13 18:51:51) from Pierre Phaneuf

Saving what again?

As it turns out, this year's change in the implementation of daylight "savings" ended up not saving anything, and actually just causing extra annoyance. The US Congress seems completely taken by surprise by the fact that changing the time does not magically create more sunlight. That extra hour in the evening, scientists and the Department of Energy reminds them, is actually offset by an hour less in the morning! Imagine that!

Seems like there is not even a measurable energy savings. If anything, the biggest impact of the daylight savings change is that a bunch of computerized gadgets needed to be updated, and people with their Blackberry and Palm not being sure if the time was adjusted (some changed the time manually, only to have it change by another at the old switch-over date, for example).

Down with daylight savings! End the madness!

Syndicated 2007-05-21 05:44:15 from Pierre Phaneuf's Diary

Saving what again?

As it turns out, this year's change in the implementation of daylight "savings" ended up not saving anything, and actually just causing extra annoyance. The US Congress seems completely taken by surprise by the fact that changing the time does not magically create more sunlight. That extra hour in the evening, scientists and the Department of Energy reminds them, is actually offset by an hour less in the morning! Imagine that!

Seems like there is not even a measurable energy savings. If anything, the biggest impact of the daylight savings change is that a bunch of computerized gadgets needed to be updated, and people with their Blackberry and Palm not being sure if the time was adjusted (some changed the time manually, only to have it change by another at the old switch-over date, for example).

Down with daylight savings! End the madness!

Syndicated 2007-05-21 05:41:05 (Updated 2007-05-21 05:44:15) from Pierre Phaneuf

My birthday is coming up, you know?

OMG, I so want one of these!

Syndicated 2007-05-16 06:59:38 from Pierre Phaneuf

Reboot

Last weekend, I got my residency permit turned down, which, to make a long story short, means that we'll be heading back to Canada. Seems like I was misdirected by the Consulat de France in Montreal, and from what I hear, it seems to be something they've done a few times ([info]azrhey worked in a place here where they hire a lot of foreigners, due to language skills).

So, it looks like I'm going to be looking for a job back in Montreal.

My weapons of choice are C++ and Perl, but being a Unix/Linux hacker, of course, I am not limited to those, they're just the ones I'm most deadly with. I am comfortable with meta-programming (mostly, but not limited to that of C++ templates), continuations/coroutines, closures, multithreading, as well as event-driven state machines. I am quite effective at code refactoring, particularly in strongly typed languages, where I can use the typing system to my advantage.

I am deeply intimate with Unix/Linux, mainly in the area of network programming (sockets, networking protocols, other forms of IPC). On Linux, I am quite familiar with a number of the high-performance APIs. I have a deep knowledge of the HTTP protocol (and some of its derivatives). I have experience writing Apache modules. I know the difference between bandwidth and latency (and wish more people did too). I have some experience with developing distributed software. I have a higher-than-average knowledge of ELF and Mach-O binary formats, particularly of how symbol resolution works. I know a good deal about component software (dynamically loading modules, for example), and ABI stability issues. While I am not a master at it, I have some Linux kernel development experience as well. I know what make is doing, and why.

Finally, I also have some experience doing project and release management, where I feel I did a pretty good job, and would certainly like to do more of it. I am familiar with the free and open source software community, belonging to a number of projects, including some that were part of my work.

Syndicated 2007-05-12 17:45:47 from Pierre Phaneuf

316 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!