Re: g++ 3.4.5 doesn't zero-initialize
* Balog Pal:
"Alf P. Steinbach" <alfps@start.no>
.
Grr.
What's wrong with this code?
struct WndClassEx: WNDCLASSEX
{
WndClassEx(
cppx::WideString const& name,
Params const& params
)
: WNDCLASSEX()
{
cbSize = sizeof( WNDCLASSEX );
style = params.style();
lpfnWndProc = &DefWindowProc;
hInstance = params.module();
hCursor = ::LoadCursor( 0, IDC_ARROW );
hbrBackground = reinterpret_cast<HBRUSH>( COLOR_BTNFACE +
1 );
lpszClassName = name.cStr();
}
WndClassEx const* ptr() const
{
return this;
}
};
Answer: nothing in particular, at least when one knows that it's just a
little local helper class where 'name' arg has lifetime guaranteed to be
enough.
The problem is you build on working 'value-init' that is known to have
real-world problems.
So has everything. :-)
I'd not know what to not avoid.
I think the statement is founded on blissful ignorance of how many constructs of
C++ that have real world problems with some popular compilers.
That includes exceptions, it includes RTTI such as dynamic_cast, even for-loops
(scope). It even includes standard 'main' (linking).
Avoiding for-loops, standard main, RTTI, default-initialization, exceptions...,
one would have, well, not C++!
But MinGW g++ doesn't zero-initialize the WNDCLASSEX as it should (this is
a plain struct with no constructor, provided by the Windows API).
Argh!
I knew old MSVC doesn't always zero-initialize /arrays/ when told to.
But I didn't know that g++ doesn't zero-initialize /structs/ when told to.
Does that version claim support for C++03? IIRC C++98 did not have the value
init for structs, and I guess the 3.x versions were about the turning point.
Even if it did claim TC1 I tend to doubt fair implementation in the first
year.
The code does not depend on C++03 value initialization.
It uses only the subset of that functionality that was present in C++98, there
known as default-initialization.
C++98 had just zero-initialization and default initialization. For a POD, such
as in the code above, the latter is the *same* as value initialization, reducing
recursively to zero-initialization of the PODs elements. Andrew Koenig (IIRC)
introduced value initialization in C++03 to help address the inconsistent
behavior one got for non-PODs, that is, for aggregate structs, e.g. if you had a
std::string in there.
And since WNDCLASSEX is a POD structure, the above should work with a C++98
compiler.
Happily it turned out that it's only in the context of a memory initializer list
that g++ goofs up the default initialization, so the code's now
struct WndClassEx: WNDCLASSEX
{
WndClassEx(
cppx::WideString const& name,
Params const& params
)
//: WNDCLASSEX()
{
*static_cast<WNDCLASSEX*>( this ) = WNDCLASSEX(); // MinGW g++.
cbSize = sizeof( WNDCLASSEX );
style = params.style();
//cbClsExtra = 0;
//cbWndExtra = 0;
lpfnWndProc = &DefWindowProc;
hInstance = params.module();
//hIcon = 0;
hCursor = ::LoadCursor( 0, IDC_ARROW );
hbrBackground = reinterpret_cast<HBRUSH>( COLOR_BTNFACE + 1 );
lpszClassName = name.cStr();
//hIconSm = 0;
}
WndClassEx const* ptr() const
{
return this;
}
};
Honestly, the calendar is 2009 by now, but I'd not rely in value init even
of current compielrs -- at least without first checking the version and
include some defense cludges in code should it migrate away...
And by the way, the gdb debugger is driving me crazy.
Too bad -- if doing windows, why not use the windows toolset? I doubt gdb
will ever come close to Visual's... If your prog is portable, it will go in
VS express, if not -- what is the wisdom behind locking into a compiler
that is poorly supported on the target platform?
On the contrary, to avoid a compiler lock-in one should compile the code with at
least 2 different compilers.
I use MingW for that purpose.
For the code that the above is part of it did spot two access issues and two
invalid extra semicolons! ;-)
However, I had to provide a number of declarations of Windows API things not
supported by the g++ Windows headers and import libraries.
Those were not, as one would expect, "new" things, but rather archaic things
where Microsoft has provided more complicated-to-use alternatives.
And if porting win code away, why to an archaic version of gcc instead of a
current?
g++ 3.4.5 *is*, unfortunately, the still current version of MinGW. :-(
There are of course "unofficial" Windows builds of later g++ versions since g++
is into version 4.x on *nix.
But I think it's best (at least for my purposes) to write code that will compile
with current versions of popupular compilers.
Cheers,
- Alf