ODR violation for std::cout etc.

Michael Veksler mveksler@tx.technion.ac.il
Tue Jul 10 16:43:00 GMT 2007


Hello,

Currently libstdc++ violates ODR:
iostream:     extern ostream cout;
global_io.cc:  fake_ostream cout;

It assumes that gcc will work fine with this. Apparently it does, for now.
After solving a similar problem in my code using a similar technique - 
to find out that it does not work for MS VS-2005 - when I had to find a 
different fix.

The question is, why does GCC has to resolve to such construction-order 
issue this way?

Idea (which I used):
don't violate ODR in global_io.cc. Instead, construct and destroy 
std::cout two times, in a safe way:

static PreSecondCtor coutPreSecondCtor(std::cout);
ostream std::cout(NULL);
static PostSecondCtor coutPostSecondCtor(coutPreSecodCtor);

When PreSecondCtor saves all relevant data of cout (error bits, state, 
rdbuf, etc.),
and then calls std::cout.~ostream();
Note that before this point, std::cout has already been constructed by 
an std::ios::Init,
and we need to avoid double construction.

In PostSecondCtor, restore the state of cout out of the saved data in 
outPreSecondCtor.

During destruction the order is reversed.

I still have a vague feeling that this solution is also undefined (since 
we are calling the constructor of std::cout, using placement new, after 
it had been automatically destroyed by the C++ environment). I don't 
have the standard near me, so I can't check.

Anyway, even if this is undefined, the situation is arguably better 
since it does not seem to break whole program compilation (like current 
implementation might).

What do you think?

Michael



More information about the Gcc mailing list