Писал для буржуинского блога на межязыке, уж не обессудьте...
I remember stepping on the stl+locale+stream+static linkage bugs as early as CB6 was major tool for our team.
They marked bug closed back at CB10 (2006) days (see attached QC link). But, it obviously re-appeared in (at least) XE6, XE7, in 64bit compiler.
Well done, C++B team, 10 years of improvement have not gone to waste :)
When porting our framework from MSVC to CB, I had to eliminate all cases of direct access to the static class members, which reside in statically linked packages. It was neccessary due to miscellaneous initialization order problems, like main code access some library class static member, which appear to have been still uninitilized, so there were AVs here and there.
The solution was using 'static initialization on demand' idiom, that is, instead of accessing SomeClass::static_Member, I use
SomeClass::staticMember() instead, where, for example:
const static_Member& SomeClass::staticMember()
{
static static_Member s_inst;
return s_inst;
}
So, there is private static instance, which is explicitly initialized once, on the first access to it.
All in all, what we have to do to work-around this calamity under CB64. AV occurs on locale's id generation. The id creation uses special nested helper class, namely (surprise!) id, declared in dinkumware64 xlocale at line 83.
// CLASS id
class _CRTIMP2P id
{ // identifier stamp, unique for each distinct kind of facet
Its operator size_t() is what we have to re-work slightly.
BEFORE, we have:
_CTHIS operator size_t()
{
// get stamp, with lazy allocation
if (_Id == 0)
{ // still zero, allocate stamp
_BEGIN_LOCK(_LOCK_LOCALE)
if (_Id == 0)
_Id = ++_Id_cnt;
_END_LOCK()
}
return (_Id);
}
private:
size_t _Id; // the identifier stamp
static int _Id_cnt;
First, I commented out static member _Id_cnt,
Second, I've added it as local static in operator itself, so,
AFTER we get:
_CTHIS operator size_t()
{
static size_t _Id_cnt = 0; ///<<< AV Cured
// get stamp, with lazy allocation
if (_Id == 0)
{ // still zero, allocate stamp
_BEGIN_LOCK(_LOCK_LOCALE)
if (_Id == 0)
_Id = ++_Id_cnt;
_END_LOCK()
}
return (_Id);
}
private:
size_t _Id; // the identifier stamp
// static int _Id_cnt;
Recompile entire project group, and viola!, finally, AVs (those, related to xlocale, at least) cured.