Thursday 6 October 2005 — This is 19 years old. Be careful.
At work we had a thorny problem in our code: when trying to make an HTTP connection for a SOAP call, the connection would fail. Reading the log files, it seemed to be a 191 error. “That’s odd, never heard of that one before,” we all said. Somehow, the spec with all the HTTP errors had never heard of it either. Could it be some vendor-specific code? We were stumped.
We lived with it for a while until a co-worker figured it out. Our logging code looked like this:
if (FAILED(hresult)) {
os << "hresult: " << std::hex << hresult << "\n";
}
if (lasterror > 0) {
os << "Win32 error: " << lasterror << "\n";
}
if (httperror > 0) {
os << "HTTP status: " << httperror << "\n";
}
Can you see what’s going on here? Bueller? Anybody?
The std::hex function modifies the ostream permanently. If the hresult was printed, then the ostream was switched into hex mode, and all numbers will be hex. The httperror value (and the lasterror value for that matter) are being written in hexadecimal. The mysterious 191 error was actually a 0x191 error, or a plain-old 401. Inserting a std::dec to set the ostream back to decimal fixed things up. We still had to fix the “unauthorized” error, but at least now we know what it is!
Comments
os << "hresult: " << std::hex << hresult << std::dec << "\n";
Is so much easier to read in classic stdio:
fprintf( os, "hresult: %x\n", hresult );
Iostreams may be typesafe and potentially less error prone (obviously not always!) but printf is much more succinct. Even Java has added printf support.
http://www.boost.org/libs/io/doc/ios_state.html
The idea is that they are stack objects which save stream state in their constructor and restore that state in their destructor. Therefore, you just create one of them in the scope of any function that changes a stream attribute and that attribute will be restored when that function exits.
Interesting link. A clever way to workaround this issue. But I still believe that formatting is something that should be associated with strings or a separate text formatter, not directly in IO streams. The Boost format library looks like it fits the bill nicely. Too bad they overloaded the mod operator to use it but the syntax isn't that bad. For example:
cout << format("Hello %s, x=%s : %d-th step \n") % "world" % 40.23 % 50;
Add a comment: