C++ – Uninitialized memory in C++Builder / Delphi

c++builderdelphiinitialization

Are uninitialized variables in Delphi guaranteed to have any particular value

  • on the stack?
  • on the heap?

Since C++Builder generally follows Delphi's design, are uninitialized variables in C++Builder guaranteed to have any particular value

  • on the stack?
  • on the heap, for member variables of classes derived from TObject?
  • on the heap, for member variables of POCOs?

I've inherited some C++Builder code that depends heavily in places on member variables being zero-initialized and am trying to figure out whether or not the language guarantees this.

Does Windows guarantee that memory is zero-initialized when it's first given to a program's stack or heap? (Edit: I realize that the program will overwrite memory as it executes and so it cannot continue to depend on this; I'm just trying to figure out the behavior that I've observed.)

Best Answer

Since caskey's answer only concerns c++ my answer for delphi:

In delphi refer to this answer by Giacomo Degli Esposti

  • Object fields are always initialized to 0, 0.0, '', False, nil or whatever applies.
  • Global variables are always initialized. (to 0)
  • Local variables are unitialized so you have to assign a value before you can use them.

ms-help://borland.bds4/bds4ref/html/Variables.htm

All credits to Giacomo Degli Esposti

Edit: "Does Windows guarantee that memory is zero-initialized when it's first given to a program's stack or heap? "

Windows guarantees that memory is zero-initialized when it's first given to a new process (otherwise you'd have a big security issue with programs being able to read other processes discarded memory regardless of permissions). However using c++ this guarantee does not help you much as the c-runtime can overwrite the memory at its discretion before your code gets any chance to use it.

Edit2: For c++ builder variables are apparently initialized for "VCL-style classes" (whatever that means, all that inherit from TObject?), see http://docs.embarcadero.com/products/rad_studio/cbuilder6/EN/CB6_DevelopersGuide_EN.pdf

I quote:

"Because data members may be used in virtual functions, it is important to understand when and how they are initialized. In Object Pascal, all uninitialized data is zero-initialized. This applies, for example, to base classes whose constructors are not called with inherited. In standard C++, there is no guarantee of the value of uninitialized data members. The following types of class data members must be initialized in the initialization list of the class’s constructor: • References • Data members with no default constructor

Nevertheless, the value of these data members, or those initialized in the body of the constructor, is undefined when the base class constructors are called. In C++Builder, the memory for VCL-style classes is zero-initialized.

Technically, it is the memory of the VCL or CLX class that is zero, that is the bits are zero, the values are actually undefined. For example, a reference is zero.

A virtual function which relies upon the value of member variables initialized in the body of the constructor or in the initialization list may behave as if the variables were initialized to zero. This is because the base class constructor is called before the initialization list is processed or the constructor body is entered.

#include <sysutils.hpp>
class Base : public TObject {
public:
    __fastcall Base() { init(); }
        virtual void __fastcall init() { }
    };
class Derived : public Base {
    public:
        Derived(int nz) : not_zero(nz) { }
        virtual void __fastcall init()
        {
        if (not_zero == 0)
        throw Exception("not_zero is zero!");
        }
    private:
        int not_zero;
};
int main(void)
{
    Derived *d42 = new Derived(42);
    return 0;
}

This example throws an exception in the constructor of Base. Because Base is constructed before Derived, not_zero, has not yet been initialized with the value of 42 passed to the constructor. Be aware that you cannot initialize data members of your VCL-style class before its base class constructors are called."