The other day we encountered a strange stack overflow when cout-ing an instance of a custom class. The stream output operator << was overloaded for the class to get a nice output, but since the class had only two std::string attributes the implementation was very simple:
using namespace std; class MyClass { public: ... private: string stringA_; string stringB_; friend ostream& operator << (ostream& out, const MyClass& myClass); }; ostream& operator << (ostream& out, const MyClass& myClass) { return out << "MyClass (A: " << myClass.stringA_ <<", B: " << myClass.stringB_ << ")" << std::endl; }
Because the debugger pointed us to a completely separate code part, our first thought was that maybe some old libraries had been accidently linked or some memory got corrupted somehow. Unfortunately, all efforts in that direction lead to nothing.
That was the time when we noticed that using old-style printf instead of std::cout did work just fine. Hm..
So back to that completely separate code part. Is it really so separate? And what does it do anyway?
We looked closer and after a few minutes we discovered the following code parts. Just look a little while before you read on, it’s not that difficult:
// some .h file somewhere in the code base that somehow got included where our stack overflow occurred:
... typedef std::string MySpecialName; ... ostream& operator << (ostream& out, const MySpecialName& name);
// and in some .cpp file nearby
... ostream& operator << (ostream& out, const MySpecialName& name) { out << "MySpecialName: " << name << std::endl; } ...
Got it? Yes, right! That overloaded out-stream operator << for MySpecialName together with that innocent looking typedef above put your program right into death by segmentation fault. Overloading the out-stream operator for a given type can be a good idea – as long as that type is not a typedef of std::string. The code above not only leads to the operator << recursively calling itself but also sucks every other part of the code into its black hole which happens to include the .h file and wants to << a std::string variable.
You just have to love C++…
One thought on “Evil operator overloading of the day”