Ah C++, OOP down to the metal. Native. I love it. I work on the C# compiler, and I do like C#, but I love C++. Incidentally the C# compiler is written in C++ and not C#, which shouldn’t be too surprising as there was no C# compiler when Microsoft first created C#. So the vast majority of my work is written in C++.
Well, C++ has some subtleties. You can run into some hard to spot bugs if you’re not careful. We found one today, with the help of a number of folks on the C++ team. Let me describe the code we had and you see if you can spot the error.
We start with a list class and an iterator class. They look something this:
class List{public: class Iterator; ...private: struct Node; Node* head;};
class List::Iterator{public: Iterator(const List& list):list(&list) { } ...private: const List* list;};
This code is fine (feel free to argue that). The following code is where the bug lies: [edit 7/12/2009: The bug is not in Foo()'s declaration. I should have included it above instead of below.]
List Foo() { ... }
void Bar(){ for (List::Iterator iter(Foo()); !iter.AtEnd(); iter.MoveNext()) { DoStuff(iter.Current()); }}
I have sort of directed you to the place where the error is by not providing any other code. So that’s a first hint. The second hint is that we only became aware of this bug once we turned on Profile Guided Optimization (PGO), which then did some optimizing in places where we did not normally see optimization.
I will reveal the answer and describe the bizarre behaviour we witnessed in my next post. We thought this was a PGO code gen bug at first. Oops.