Re: [ROOT] zero pointers on NT

From: George Heintzelman (georgeh@sparrowhawk.chm.bnl.gov)
Date: Thu Jan 25 2001 - 21:22:06 MET


> > I am a bit confused with pointer initialization on win32 and VC6.0.
>  
> > C++ standard says
> 
>   What did you mean speaking "C++ standard" ?
>   Can you give us any reference ?

I assume he means the ANSI/ISO standard C++. Available for $18 from 
www.ansi.org, document number 14882-1998. Some copies of draft versions 
are available on the web, but these are not necessarily completely 
accurate.

> > it guarantees that you get zero pointer when you define a
> > pointer. It doesn't seem to be true uder VC. Any commments?

This is not correct, however. The standard says that, for builtin types 
like pointers and int's, local variables, class data members, and 
dynamic variable allocated with the default operator new are 
uninitialized unless explicitly initialized by user code. User-defined 
types are initialized by calling their default constructor, again 
unless explicitly initialized differently.  This means that, unless the 
code writer takes steps to prevent it, most builtin variables will have 
garbage in them when first used.

For variables at global or namespace scope, however, built-in types are 
initialized with zero at program startup. User-defined types will still 
have default constructors called.

Unfortunately, this fact is not well-known among ROOT users as a 
consequence of two things:
1) ROOT style seems to encourage overuse of dynamic allocation, that 
is, allocation with operator new. In many cases where it is used that I 
have seen, it is completely unnecessary, and just adds an additional 
burden to the system.
2) The operator new supplied by ROOT zeros out the memory being 
allocated, thus appearing to initialize most things those users do to 
zero.

This means that bugs relating to failure to correctly initialize 
variables may often be undiagnosed for a long time, if the members in 
question were usually allocated using ROOT's operator new.

Finally, if the user IS doing his coding correctly and initializing his 
variables in the class initializer, he will find himself paying an 
efficiency penalty as ROOT's operator new writes 0 into the memory, and 
then he initializes it (perhaps to zero, perhaps not) in the 
constructor.

I don't like this situation. I prefer to have bugs jump up and bite me 
on the nose as early as possible, and I prefer not to pay twice for 
initialization. I feel that ROOT's operator new conceals bugs and makes 
correct code pay an extra initialization price. Since it cannot prevent 
uninitialized memory from being used in local object-type variables 
(only well-formed default constructors can do that), it does not buy 
you any real safety in exchange for that price.

Therefore I suggest, as I have before, that operator new's zeroing of 
memory be removed from ROOT.

>   Did your standard says what happens with
> 
>    void *pp[10000000]

An array of 10 million pointers to void is allocated. If this 
declaration is at global or namespace scope, they are all initialized 
to 0; otherwise they will be uninitialized. On some (many?) systems, 
this may cause the system to run out of resources (specifically, stack 
space), which is allowed (although the conditions for such resource 
exhaustion, and what must happen when it happens, are unspecified) by 
the standard. This seems to in fact be the case on my local g++ 
implementation, which segfaults for such an expression.

Note that if, in ROOT, someone were to write:

void * *pp = new (void *[10000000]);

ROOT's operator new would, in fact, spend the time to initialize all 
that memory to zero, even if the following statements were a loop 
initializing each value to something, without reading them.

George Heintzelman
georgeh@aya.yale.edu



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:34 MET