15 May 2009

I am not a fan of C++ iostreams

I'm one of those people who thinks that C++ can be an acceptable choice for a programming project. Lots of people think that C++ is dead, but I'm not one of them. I'm not a big fan of this language anymore, but it can occasionally be OK. I'm mostly somebody who programs at the level of bits/bytes/protocols/hardware/etc. so a language that lets me program at this level and also give me some OO features is alright in my book.

There are some parts of C++ that I have never liked though. The other day I was reminded of how much I have always disliked C++ iostreams.

...

I've spent the last {long period of time} wrestling with several large libraries, trying to get them all to work together. It has been like wrestling with three grizzly bears, but I don't mind: this is what I do for a living.

Anyways, around two weeks ago, before I got interrupted with something else, I noticed that my current work was dying strangely. I've been working with somebody else's code, and this code uses C++ iostreams, so, in an effort to fit in, I used C++ iostreams too. I think that the code looks somewhat ugly, but that's the way it is.

So, my code was dying strangely, and then I got interrupted for a few weeks. When I finally got back to take a look at my problem, I came to the dim realization that at some point in the program's execution my debugging output just....stopped. However, it was also obvious to me that certain parts of the program were just churning away, working just fine.

Weird.

Before I seriously got started on this project, I modified the entire project's code to compile without any warnings (as usual, this was a hugely efficient use of time...). Also, there were no memory related problems in the codebase. Nothing in the runtime was smashing one of the iostreams-related data-structures, which could explain the root-cause of the program's output just stopping.

Eventually, after a bit of searching around, I figured out what was going on: a part of the program's code (part that I had never really looked at in detail) was printing out some C++ classes with the iostreams library. The problem was that, as part of my modifications, I had some NULL pointers to various things -- and parts of the code were attempting to print these too.

To cut to the chase, can you guess what the following code produces with my platform's C++ implementation? (generic Linux x86_64 box, g++ 4.x.y, program compiles cleanly with "-Wall -pedantic")


#include <iostream>

int main(int argc, char *argv[])
{
     char *p = NULL;

     std::cout << p << std::endl;
}



Answer: my platform's C++ implementation prints ABSOLUTELY NOTHING when it runs this code. This pretty much mimics the problem I was having with my much larger program.

Since we're on the subject, can you guess what this program outputs on my platform? (gcc 4.x.y, program compiles cleanly with "-Wall -pedantic")

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
     char *p = NULL;
 
     printf("%s\n", p);

     printf("Hello World\n");

     return 0;
 }


Answer: this program prints out something completely reasonable.

The thing that bugs me about the behavior of the C++ program is that not only does the iostreams implementation not tell me about the NULL pointer, but this action also seems to corrupt the internal state of the iostreams library itself, thus causing ABSOLUTELY NO SUBSEQUENT OUTPUT. I mean, surely this must be a common enough occurence in the Real World, no? The designers of iostreams must be happy with their type-safe interface to the rest of the thorny things that might go on in any C++ program, but this particular implementation failed in a manner that cost me a couple of hours of debugging time.

(As a side-note: yes, I know quite a lot about the internal plumbing of C++ to understand why an implementation might not print out the code's NULL pointer here -- yeah, yeah, I know, "undefined behavior". Yawn. Just because I understand what might be going wrong here doesn't imply that I am a fan of this behavior)

I'm just not a big fan of C++ iostreams. I much prefer strategic use of the battle-tested and known-to-be-reliable stdio library -- even in C++ code. Maybe iostreams would be a lot more attractive to me if I commonly programmed at a higher layers, but at that point I'd almost certainly favor Java over C++.

No comments: