views:

119

answers:

2

I have a dynamic array myArr. What is stored in the memory in myArr when we use SetLength on it? Is it '00'? Or undefined?

SetLength allocates 16 bytes of memory for myArr in this case.

myArr : array of byte;

SetLength(myArr, 16);
+2  A: 

It is initialized to 0

SetLength internally calls System.DynArraySetLength.
Using Delphi 5, the memory is filled with #0.

  // Set the new memory to all zero bits
  FillChar((PChar(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0);

I assume this behavior has not changed in more recent versions of Delphi.

Lieven
+1 this is true in Delphi 7 - whatever the doc says, the code in System.pas DOES initialize the dynamic array data with zero bytes.
A. Bouchez
@Lieven, True but you can't really rely on that. It's not part of the specifications (contrary to initialized types) and can change without notice.
François
True but what is the alternative? Initializing it yourself, knowing it to be a wast of time? I would rely on it and add a testcase verifying it each day with our daily builds. Should it change (without notice), the daily build picks it up.
Lieven
@Lieven: you're right. EMB won't change this, because they know it'll break a lot of softwares built with Delphi. And they need to initialize the strings and dynamic arrays to 0 before using it, so filling the whole array with 0 is the fastest way of doing it. Fillchar is fast, and some faster code can be found in the fastcode project.
A. Bouchez
@Lieven: Yes, if your code is dependent on it being initialized. The documentation says "the content of newly allocated space is undefined", and because they happen to define something now is not to be relied upon. Until the documentation changes, your only reliance is that you can't depend on the content being anything but junk.
Ken White
+9  A: 

Quoted from the Delphi 7 help, "For a long-string or dynamic-array variable, SetLength reallocates the string or array referenced by S to the given length. Existing characters in the string or elements in the array are preserved, but the content of newly allocated space is undefined. The one exception is when increasing the length of a dynamic array in which the elements are types that must be initialized (strings, Variants, Variant arrays, or records that contain such types). When S is a dynamic array of types that must be initialized, newly allocated space is set to 0 or nil."

From my observation, for static array, uninitialized elements contain random data. For dynamic array, AFAIK since Delphi 7, uninitialized elements contain their default nothing value. However, you shouldn't rely on this fact because it was implementation detail of SetLength. You should follow the official documentation instead.

Vantomex
-1 this is not true in Delphi 7 - whatever the doc says, the code in System.pas DOES initialize the dynamic array data with zero bytes
A. Bouchez
Can you guarantee such a behaviour will stay as now in the future versions of Delphi? For your comment of Delphi 7, please read the second paragraph.
Vantomex
To avoid any regression in existing applications, I can't guarantee EMB could not change the code... but they are quite conservative about such thinks... they know that a lot of code rely on this undocumented behavior. Since the corresponding Delphi 5/6/7...2010/XE system.pas code is in pure pascal, and is easy to convert to 64 bit (convert PChar to NativeInt or such), I don't find any reason why they should change the implementation in the future: filling all new memory at once is faster than initialize individual string, variants and such.
A. Bouchez
About your observation (we don't speak about static arrays here) it's perhaps not precise enough: the fillchar is called every time the SetLength() = DynArraySetLength code is called. So "default value" is always 0 here.
A. Bouchez
I said "uninitialized elements contain their *default value*." or maybe it is more precise as *nothing value*, It means, for numerical data types (Byte, Word, Integer, Double) it is `0`, for string data types (AnsiString, UnicodeString) it is empty, and so on.
Vantomex
@Vantomex: of course, I didn't say you were wrong, but I just wanted thinks to be clearer. There is no official "default" value for an integer, for instance, but it's always filled with 0 in an array of integer.
A. Bouchez
It is wrong to say that they always avoid regression in existing applications just because there a lot of codes rely on an undocumented behaviour. Microsoft have been saying many times in MSDN that we should never rely on undocumented behaviour because they may be changed without further notice. Didn't you know that SoftICE was discontinued because it has many codes rely on undocumented Windows APIs and behaviours? and they, of course, thought in the past that those APIs and behaviours should never changed in the future, but time has proved that they were wrong.
Vantomex