Recent

Author Topic: Dynamic array as a typed constant  (Read 1935 times)

avk

  • Hero Member
  • *****
  • Posts: 752
Dynamic array as a typed constant
« on: November 05, 2022, 10:49:17 am »
Is this intended?
Code: Pascal  [Select][+][-]
  1. program test;
  2. {$mode objfpc}{$j-}
  3. const
  4.   Items: array of Integer = (1, 2, 3);
  5. var
  6.   I: Integer;
  7. begin
  8.   for I := 0 to High(Items) do begin
  9.     Inc(Items[I]);
  10.     WriteLn(Items[I]);
  11.   end;
  12. end.
  13.  

It compiles and runs for at least the current Linux64 compiler.

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Dynamic array as a typed constant
« Reply #1 on: November 05, 2022, 10:58:40 am »
const often seems to act more like static in C

Code: Pascal  [Select][+][-]
  1. program test;
  2. {$mode objfpc}{$j-}
  3. {$WriteableConst off}
  4. const
  5.   Items: array of Integer = (1, 2, 3);
  6. var
  7.   I: Integer;
  8. begin
  9.   for I := 0 to High(Items) do begin
  10.     Inc(Items[I]);
  11.     WriteLn(Items[I]);
  12.   end;
  13. end.
  14.  

Compiles and run for me as well.... (Also on current Linux64 compiler)

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Dynamic array as a typed constant
« Reply #2 on: November 05, 2022, 11:08:42 am »
This also works:

Code: Pascal  [Select][+][-]
  1. program test2;
  2. {$mode objfpc}{$j-}
  3. {$WriteableConst off}
  4.  
  5. type
  6.   TArrayInteger = array of Integer;
  7.  
  8. procedure process_array(const Items: TArrayInteger);
  9. var
  10.   I: Integer;
  11. begin
  12.   for I := 0 to High(Items) do begin
  13.     Inc(Items[I]);
  14.     WriteLn(Items[I]);
  15.   end;
  16. end;
  17.  
  18. begin
  19.   process_array([1,2,3]);
  20. end.

As I've said before,  const is cursory and shallow in Free Pascal.

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Dynamic array as a typed constant
« Reply #3 on: November 05, 2022, 11:16:19 am »
This fails:

Code: Pascal  [Select][+][-]
  1. program test3;
  2. {$mode objfpc}{$j-}
  3. {$WriteableConst off}
  4.  
  5. type
  6.   TArrayInteger = array of Integer;
  7.  
  8. procedure process_array(const Items: TArrayInteger);
  9. var
  10.   I: Integer;
  11. begin
  12.   Items := [10, 11, 12];
  13.   for I := 0 to High(Items) do begin
  14.     Inc(Items[I]);
  15.     WriteLn(Items[I]);
  16.   end;
  17. end;
  18.  
  19. begin
  20.   process_array([1,2,3]);
  21. end.
  22.  

Code: Text  [Select][+][-]
  1. $ fpc test3.pas
  2. Free Pascal Compiler version 3.3.1 [2022/11/02] for x86_64
  3. Copyright (c) 1993-2022 by Florian Klaempfl and others
  4. Target OS: Linux for x86-64
  5. Compiling test3.pas
  6. test3.pas(12,3) Error: Can't assign values to const variable
  7. test3.pas(22) Fatal: There were 1 errors compiling module, stopping
  8. Fatal: Compilation aborted
  9. Error: /home/dev/fpc_usr/lib/fpc/3.3.1/ppcx64 returned an error exitcode
  10.  

Whereas this succeeds:

Code: Pascal  [Select][+][-]
  1. program test4;
  2. {$mode objfpc}{$j-}
  3. {$WriteableConst off}
  4.  
  5. type
  6.   TArrayInteger = array of Integer;
  7.  
  8. procedure process_array(Items: TArrayInteger);
  9. var
  10.   I: Integer;
  11. begin
  12.   Items := [10, 11, 12];
  13.   for I := 0 to High(Items) do begin
  14.     Inc(Items[I]);
  15.     WriteLn(Items[I]);
  16.   end;
  17. end;
  18.  
  19. begin
  20.   process_array([1,2,3]);
  21. end.

const only seems to apply to the variable itself, not the contents if a pointer or an array.

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Dynamic array as a typed constant
« Reply #4 on: November 05, 2022, 12:02:12 pm »
For const records it is enforced.

Code: Pascal  [Select][+][-]
  1. program test6;
  2. {$mode objfpc}{$j-}
  3. {$WriteableConst off}
  4.  
  5. type
  6.   SomeRec = record
  7.         a: integer;
  8.   end;
  9.  
  10. const
  11.   some: SomeRec = (a: 4);
  12.  
  13. begin
  14.   some.a := 5;
  15. end.

Code: Text  [Select][+][-]
  1. $ fpc test6.pas
  2. Free Pascal Compiler version 3.3.1 [2022/11/02] for x86_64
  3. Copyright (c) 1993-2022 by Florian Klaempfl and others
  4. Target OS: Linux for x86-64
  5. Compiling test6.pas
  6. test6.pas(14,3) Error: Can't assign values to const variable
  7. test6.pas(16) Fatal: There were 1 errors compiling module, stopping
  8. Fatal: Compilation aborted
  9. Error: /home/dev/fpc_usr/lib/fpc/3.3.1/ppcx64 returned an error exitcode
  10.  



Code: Pascal  [Select][+][-]
  1. program test5;
  2. {$mode objfpc}{$j-}
  3. {$WriteableConst off}
  4.  
  5. type
  6.   SomeRec = record
  7.         a: integer;
  8.   end;
  9.  
  10. procedure process_rec(const rec: SomeRec);
  11. begin
  12.         rec.a := 20;
  13.         WriteLn(rec.a);
  14. end;
  15.  
  16. var
  17.   some: SomeRec = (a: 4);
  18.  
  19. begin
  20.   some.a := 5;
  21.   process_rec(some);
  22. end.
  23.  

Code: Text  [Select][+][-]
  1. $ fpc test5.pas
  2. Free Pascal Compiler version 3.3.1 [2022/11/02] for x86_64
  3. Copyright (c) 1993-2022 by Florian Klaempfl and others
  4. Target OS: Linux for x86-64
  5. Compiling test5.pas
  6. test5.pas(12,2) Error: Can't assign values to const variable
  7. test5.pas(23) Fatal: There were 1 errors compiling module, stopping
  8. Fatal: Compilation aborted
  9. Error: /home/dev/fpc_usr/lib/fpc/3.3.1/ppcx64 returned an error exitcode
  10.  

440bx

  • Hero Member
  • *****
  • Posts: 4070
Re: Dynamic array as a typed constant
« Reply #5 on: November 05, 2022, 12:19:21 pm »
Is this intended?
At least in theory, it is a bug because the constant is not writeable.

I reported something quite similar a while back (it may be a variation of the same bug): https://forum.lazarus.freepascal.org/index.php/topic,54553.msg405170.html#msg405170
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Dynamic array as a typed constant
« Reply #6 on: November 05, 2022, 12:34:17 pm »
@Bogen85, {$j-} means {$writeableconst off}

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Dynamic array as a typed constant
« Reply #7 on: November 05, 2022, 12:49:20 pm »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Dynamic array as a typed constant
« Reply #8 on: November 05, 2022, 09:50:07 pm »
const often seems to act more like static in C

Don't go there. The topic's been done to death, and the core developers are strongly against any "syntactic sugar" even if the intention is to conform to industry expectations.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: Dynamic array as a typed constant
« Reply #9 on: November 05, 2022, 09:57:39 pm »
Is this intended?
Code: Pascal  [Select][+][-]
  1. program test;
  2. {$mode objfpc}{$j-}
  3. const
  4.   Items: array of Integer = (1, 2, 3);
  5. var
  6.   I: Integer;
  7. begin
  8.   for I := 0 to High(Items) do begin
  9.     Inc(Items[I]);
  10.     WriteLn(Items[I]);
  11.   end;
  12. end.
  13.  

It compiles and runs for at least the current Linux64 compiler.

While the compiler could be improved to reject the Inc on a typed dynamic array constant right away the effect on the current code at runtime is platform dependent, because not on every platform the data will be put into a readonly section. For example on Windows (no matter if 32- or 64-bit) your code will result in a runtime error. On Linux however the compiler currently does not support putting typed constants into a readonly section due to requirements for relocations. And other platforms (like DOS) simply don't support that at all...

But you could report a bug for the compiler not rejecting the Inc at compile time. This is likely a remnant of the fact that typed dynamic array constants were only introduced in FPC 3.2.0.

ASerge

  • Hero Member
  • *****
  • Posts: 2250
Re: Dynamic array as a typed constant
« Reply #10 on: November 06, 2022, 06:39:47 am »
While the compiler could be improved to reject the Inc on a typed dynamic array constant right away the effect on the current code at runtime is platform dependent, because not on every platform the data will be put into a readonly section. For example on Windows (no matter if 32- or 64-bit) your code will result in a runtime error. On Linux however the compiler currently does not support putting typed constants into a readonly section due to requirements for relocations. And other platforms (like DOS) simply don't support that at all...

But you could report a bug for the compiler not rejecting the Inc at compile time. This is likely a remnant of the fact that typed dynamic array constants were only introduced in FPC 3.2.0.
This is a controversial point. From my point of view {$WRITEABLECONST OFF} refers only to the Items variable, but not to its contents, which, according to the documentation, is always located in the heap and is logically always writable.

Code: Pascal  [Select][+][-]
  1. {$IFDEF FPC}
  2.   {$MODE OBJFPC}
  3. {$ENDIF}
  4. {$APPTYPE CONSOLE}
  5. {$WRITEABLECONST OFF}
  6. const
  7.   Items: array of Integer = {$IFDEF FPC}(1, 2, 3){$ELSE}[1, 2, 3]{$ENDIF};
  8. var
  9.   I: Integer;
  10. begin
  11.   for I := 0 to High(Items) do begin
  12.     Items[I] := Items[I] * 2;
  13.     WriteLn(Items[I]);
  14.   end;
  15.   ReadLn;
  16. end.
This code executes with an error in Windows if compiled in FPC, but without errors if compiled in Delphi.

440bx

  • Hero Member
  • *****
  • Posts: 4070
Re: Dynamic array as a typed constant
« Reply #11 on: November 06, 2022, 06:50:34 am »
From my point of view {$WRITEABLECONST OFF} refers only to the Items variable, but not to its contents, which, according to the documentation, is always located in the heap and is logically always writable.
But, in the case of a typed constant, "Items" is the starting address of the array of integers, therefore, "Items" and its "contents" are the same thing (at least for the first element.)

This code executes with an error in Windows if compiled in FPC, but without errors if compiled in Delphi.
IMO, FPC's result in Windows is the correct one (the array is const, therefore not writeable.)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

ASerge

  • Hero Member
  • *****
  • Posts: 2250
Re: Dynamic array as a typed constant
« Reply #12 on: November 06, 2022, 07:09:59 am »
IMO, FPC's result in Windows is the correct one (the array is const, therefore not writeable.)
I don't agree. According to the documentation Dynamic array types "A dynamic array is stored as a pointer to a block of memory on the heap". In this case, the compiler placed the contents of the array in the data block, and not in the heap, which violated the convention on dynamic arrays.

440bx

  • Hero Member
  • *****
  • Posts: 4070
Re: Dynamic array as a typed constant
« Reply #13 on: November 06, 2022, 07:20:10 am »
IMO, FPC's result in Windows is the correct one (the array is const, therefore not writeable.)
According to the documentation Dynamic array types "A dynamic array is stored as a pointer to a block of memory on the heap". In this case, the compiler placed the contents of the array in the data block, and not in the heap, which violated the convention on dynamic arrays.
That's a valid point but, when declaring a constant the compiler cannot know where to put the values assigned to the constant.  There are only two ways of handling the problem, the first is what the compiler did, place the constant in a read-only segment and the other would be to generate code to allocate a block of memory at runtime, save the address into "Items" (which means "Items" cannot be a constant as declared) and initialize that block of memory with the declared values.  That's a lot more complications than a compiler should be indulging into.

I believe the documentation is a bit too "imprecise" or "general" because based on what it says, you have a valid point but, it's not a practical (maybe not even viable) method for a "const".
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: Dynamic array as a typed constant
« Reply #14 on: November 06, 2022, 04:02:46 pm »
While the compiler could be improved to reject the Inc on a typed dynamic array constant right away the effect on the current code at runtime is platform dependent, because not on every platform the data will be put into a readonly section. For example on Windows (no matter if 32- or 64-bit) your code will result in a runtime error. On Linux however the compiler currently does not support putting typed constants into a readonly section due to requirements for relocations. And other platforms (like DOS) simply don't support that at all...

But you could report a bug for the compiler not rejecting the Inc at compile time. This is likely a remnant of the fact that typed dynamic array constants were only introduced in FPC 3.2.0.
This is a controversial point. From my point of view {$WRITEABLECONST OFF} refers only to the Items variable, but not to its contents, which, according to the documentation, is always located in the heap and is logically always writable.

Global variables and typed constants are located neither on the heap, nor the stack. They are located in the data section of the binary.

This code executes with an error in Windows if compiled in FPC, but without errors if compiled in Delphi.

FPC decided years ago already to break compatiblity with Delphi here to improve type safety. When you have a non-writable constant then it makes sense for it to really be not writable.

IMO, FPC's result in Windows is the correct one (the array is const, therefore not writeable.)
I don't agree. According to the documentation Dynamic array types "A dynamic array is stored as a pointer to a block of memory on the heap". In this case, the compiler placed the contents of the array in the data block, and not in the heap, which violated the convention on dynamic arrays.

Since the introduction of typed dynamic array constants (which was in 3.2.0) the documentation hasn't been updated regarding this, cause these plus their values are not located on the heap.

 

TinyPortal © 2005-2018