Recent

Author Topic: dynamic array bug ?  (Read 5714 times)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: dynamic array bug ?
« Reply #15 on: June 26, 2018, 09:09:10 pm »
Quote
Using an uninitialised variable and then finding it contains (or points to) non-random data is not a compiler bug, but a programmer failing. In this simple case your uninitialised Result happens to pick up the 'same' data consistently. But this is an implementation detail, and cannot be relied on. Result is undefined until you assign a value to it.

Not agreed in this case. The documentation does not tell me to initialise the argument of Setlength before using it. SetLength itself does the initialisation.
Incorrect. SetLength either initializes or re-initializes the contents. In short if the argument passed is an already initialized variable it tries to preserve the existing data if possible (ee on expanding but not on shrinking). So yes it requires a proper initialized variable to decide if it needs to preserve existing data or not.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: dynamic array bug ?
« Reply #16 on: June 26, 2018, 09:31:04 pm »
Quote
Incorrect. SetLength either initializes or re-initializes the contents. In short if the argument passed is an already initialized variable it tries to preserve the existing data if possible (ee on expanding but not on shrinking). So yes it requires a proper initialized variable to decide if it needs to preserve existing data or not.

I understand that. However the compiler knows that the function shall return a dynamic array, hence it could as well set implicitly result := nil before the Setlength() call. It does not do so, and that is all but clear.    
There are possibly reasons for that behaviour, but this is a rather dangerous construct within a language praised as "safe": You may use setlength(x) anywhere in your code without initialising x, ONLY within a function it goes bonkers. What is the logic of that ?

Related bug report 0030321 already claims this behaviouer is poorly documented; however even if documented, I would find it difficult to accept. The report report says "fixed in 3.1.1" but from Jonas' response to my report 0030321 it is not quite clear if actually the code has been changed, or only the documentation.


taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: dynamic array bug ?
« Reply #17 on: June 26, 2018, 09:40:33 pm »
Quote
Incorrect. SetLength either initializes or re-initializes the contents. In short if the argument passed is an already initialized variable it tries to preserve the existing data if possible (ee on expanding but not on shrinking). So yes it requires a proper initialized variable to decide if it needs to preserve existing data or not.

I understand that. However the compiler knows that the function shall return a dynamic array, hence it could as well set implicitly result := nil before the Setlength() call. It does not do so, and that is all but clear.   
true.
There are possibly reasons for that behaviour, but this is a rather dangerous construct within a language praised as "safe":
safe not fool proof.
You may use setlength(x) anywhere in your code without initialising x, ONLY within a function it goes bonkers. What is the logic of that ?
Incorrect. It is unsafe to use setlength in uninitialized variables in any place, this may lead to overflow conditions. Never do that.
Related bug report 0030321 already claims this behaviouer is poorly documented; however even if documented, I would find it difficult to accept. The report report says "fixed in 3.1.1" but from Jonas' response to my report 0030321 it is not quite clear if actually the code has been changed, or only the documentation.
Yeah your logic is a bit hard to accept for me too, but if it ends up with (at least) better documentation no matter what solution is implemented its enough for me. I'm already initializing everything my self already and neve rely on the compiler to do so. In fact if tomorrow the compiler decided that no variable is initialized for speed reasons my code is safe.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 14213
  • Probably until I exterminate Putin.
Re: dynamic array bug ?
« Reply #18 on: June 26, 2018, 09:45:22 pm »
Only the docs
Specialize a type, not a var.

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: dynamic array bug ?
« Reply #19 on: June 26, 2018, 09:46:16 pm »
Quote
I'm already initializing everything my self already and neve rely on the compiler to do so. In fact if tomorrow the compiler decided that no variable is initialized for speed reasons my code is safe.

Which means if you have something like
Code: Pascal  [Select][+][-]
  1. var a: array of integer;
  2. SetLength (a,100);
  3.  

you would shove an "a := nil" between any such statements ?

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: dynamic array bug ?
« Reply #20 on: June 26, 2018, 09:49:13 pm »
Quote
I'm already initializing everything my self already and neve rely on the compiler to do so. In fact if tomorrow the compiler decided that no variable is initialized for speed reasons my code is safe.

Which means if you have something like
Code: Pascal  [Select][+][-]
  1. var a: array of integer;
  2. SetLength (a,100);
  3.  

you would shove an "a := nil" between any such statements ?
usually

Code: Pascal  [Select][+][-]
  1. var
  2.   a: array of integer =nil;
  3. begin
  4.   SetLength (a,100);
  5.  
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: dynamic array bug ?
« Reply #21 on: June 26, 2018, 09:58:14 pm »
Ok, but taking that a step further, we might also ask whether the compiler will tomorrow still fill the array with zeroes, so we would prudently add something like fillchar (a[0], 100*sizeof(integer), 0);...

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: dynamic array bug ?
« Reply #22 on: June 26, 2018, 10:03:26 pm »
Ok, but taking that a step further, we might also ask whether the compiler will tomorrow still fill the array with zeroes, so we would prudently add something like fillchar (a[0], 100*sizeof(integer), 0);...
I already have a unit with procedures that do that for a number of standard and custom data types. I'm not as rigorous in its use as I'm with initializing variables, but its used occasionally, I do like to be sure that the state of my memory is known especially if it does not involve some other form of initialization (eg load from file).
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: dynamic array bug ?
« Reply #23 on: June 26, 2018, 10:11:06 pm »
It's not a bug, just non-optimal generated code. Maybe just to be more safe (unnecessarily safe).
First, what does the SetLength function do?
Pseudocode:
Code: Pascal  [Select][+][-]
  1. procedure SetLength(var A: dynamic_array; NewLen: SizeInt);
  2. begin
  3.   if RefCount(A) <> 1 then
  4.     A := MakeCopy(A); // all other reference not change, A has RefCount = 1
  5.   ReallocInPlace(A, NewLen * SizeOf(A[0]));
  6.   if TypeOf(A[0]) contains ref types then
  7.     initialize new members
  8. end;
Second, FPC use temp variable, and this is look like bug:
Code: Pascal  [Select][+][-]
  1. // A := NewVector(3);
  2. NewVector(3, Temp); // before call Temp is nil
  3. A := Temp; // after call A and Temp are the same, refcount = 2
  4. //...
  5. // B := NewVector(3);
  6. NewVector(3, Temp); // before call Temp has refcount 2, as result (see SelLength above) makes a copy of the array
  7. B := Temp; // after call A refcount=1, B and temp are the same with ref count = 2
  8.  
Delphi does not use a temporary variable in this case.

 

TinyPortal © 2005-2018