Recent

Author Topic: [Solved] Simple string loop  (Read 1567 times)

tennis

  • New Member
  • *
  • Posts: 11
[Solved] Simple string loop
« on: July 11, 2020, 03:37:07 pm »
I recently deflected from Python and are new to Object Pascal so bear with me.
Found some simple code with a behavior which baffles me:

 
program stringlooptest;
{$mode objfpc}{$H+}
var
  name : string;
begin
  for name in ['project','customer','supplier'] do
    WriteLn(name);
end.


this output:

project
custome
supplie


It seems the length of the string is capped to the length of
the first string in the array.

This compiles with out any warning.
Is this the intended behavior?
« Last Edit: July 12, 2020, 01:06:33 pm by tennis »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Simple string loop
« Reply #1 on: July 11, 2020, 04:09:36 pm »
I doubt that it is intended behaviour.
The array constructor in this case behaves as if you had declared it like this:
Code: Pascal  [Select][+][-]
  1. program stringlooptest2;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils;
  7.  
  8. type
  9.   TS7Array = array of string[7];
  10.  
  11. var
  12.   name : String;
  13.   sa: TS7Array = ('project','customer','supplier');
  14. begin
  15.   for name in sa do
  16.     WriteLn(name);
  17.   ReadLn;
  18. end.
and this code, as expected, gives a compiler warning that two strings are longer than the allocated storage.
If you put the longest string first in your example, the problem goes away. So clearly the anonymous array the compiler constructs is predicated only on the first string in the series, and for some reason is also a shortstring, even though you specified {$H+}.
Looks like a bug to me.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Simple string loop
« Reply #2 on: July 11, 2020, 05:30:31 pm »
This compiles with out any warning.
Is this the intended behavior?

This should indeed produce the correct result. Please report a bug with your code as an example so that it isn't forgotten.

tennis

  • New Member
  • *
  • Posts: 11
Re: Simple string loop
« Reply #3 on: July 12, 2020, 01:05:34 pm »
Thanks for the replies.

Bug filed in issue 37338 : https://bugs.freepascal.org/view.php?id=37338

MaxCuriosus

  • Full Member
  • ***
  • Posts: 136
Re: [Solved] Simple string loop
« Reply #4 on: July 12, 2020, 01:30:08 pm »
What version of fpc was it?

Leledumbo

  • Hero Member
  • *****
  • Posts: 8746
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: [Solved] Simple string loop
« Reply #5 on: July 12, 2020, 01:52:15 pm »
I've reported this bug before: https://bugs.freepascal.org/view.php?id=32034
Nobody seems interested or it might be too difficult despite the easy look? Nevertheless, workaround exists so yeah this might be ignorable.

tennis

  • New Member
  • *
  • Posts: 11
Re: [Solved] Simple string loop
« Reply #6 on: July 12, 2020, 02:10:52 pm »
Version was FPC3.20

The behavior is no problem, but I would expect it should simple to
implement a compiler warning, otherwise it is easy to create
very hard bugs to find. A newbie would not expect this to
fail.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8746
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: [Solved] Simple string loop
« Reply #7 on: July 12, 2020, 03:02:39 pm »
Version was FPC3.20

The behavior is no problem, but I would expect it should simple to
implement a compiler warning, otherwise it is easy to create
very hard bugs to find. A newbie would not expect this to
fail.
I would against that "solution", as this is a code generator bug, i.e. by design it should not do so, but as we expected, so a warning should not be required in the first place.

Anyway, it's not difficult to find the cause. Using OP's program, I try seeing the difference between if the first element is 'project' and if it's 'projects', diff tells me this:
Code: ASM  [Select][+][-]
  1. # [6] for name in ['project','customer','supplier'] do        | # [6] for name in ['projects','customer','supplier'] do
  2.         movl    _$STRINGLOOPTEST$_Ld1,%eax                    |         movq    _$STRINGLOOPTEST$_Ld1,%rax
  3.         movl    %eax,24(%rsp)                                 |         movq    %rax,24(%rsp)
  4.         movw    _$STRINGLOOPTEST$_Ld1+4,%ax                   |         movq    _$STRINGLOOPTEST$_Ld2,%rax
  5.         movw    %ax,28(%rsp)                                  |         movq    %rax,32(%rsp)
  6.         movb    _$STRINGLOOPTEST$_Ld1+6,%al                   |         movq    _$STRINGLOOPTEST$_Ld3,%rax
  7.         movb    %al,30(%rsp)                                  |         movq    %rax,40(%rsp)
  8.         movl    _$STRINGLOOPTEST$_Ld2,%eax                    <
  9.         movl    %eax,31(%rsp)                                 <
  10.         movw    _$STRINGLOOPTEST$_Ld2+4,%ax                   <
  11.         movw    %ax,35(%rsp)                                  <
  12.         movb    _$STRINGLOOPTEST$_Ld2+6,%al                   <
  13.         movb    %al,37(%rsp)                                  <
  14.         movl    _$STRINGLOOPTEST$_Ld3,%eax                    <
  15.         movl    %eax,38(%rsp)                                 <
  16.         movw    _$STRINGLOOPTEST$_Ld3+4,%ax                   <
  17.         movw    %ax,42(%rsp)                                  <
  18.         movb    _$STRINGLOOPTEST$_Ld3+6,%al                   <
  19.         movb    %al,44(%rsp)                                  <
  20.         movl    40(%rsp),%eax                                 |         movq    40(%rsp),%rax
  21.         movl    %eax,16(%rsp)                                 |         movq    %rax,16(%rsp)
  22.         movb    44(%rsp),%al                                  <
  23.         movb    %al,20(%rsp)                                  <
  24.         movl    $6,%edx                                       |         movl    $7,%edx
  25.         imulq   $7,%rax,%rax                                  |         leaq    (%rsp,%rax,8),%rsi
  26.         leaq    (%rsp,%rax),%rsi                              <
  27.         .ascii  "project\000"                                 |         .ascii  "projects\000"
  28.  
The line after leaq before .ascii calls fpc_chararray_to_ansistr, but %edx which I suppose stores the char array length (tested by using 'projec' as first element, it then became $5), remains a constant. This makes fpc_chararray_to_ansistr always return the same length strings.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: [Solved] Simple string loop
« Reply #8 on: July 12, 2020, 04:53:19 pm »
I've reported this bug before: https://bugs.freepascal.org/view.php?id=32034
Nobody seems interested or it might be too difficult despite the easy look? Nevertheless, workaround exists so yeah this might be ignorable.

More like too many bugs to keep track of... :-[

Leledumbo

  • Hero Member
  • *****
  • Posts: 8746
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: [Solved] Simple string loop
« Reply #9 on: July 16, 2020, 11:32:42 am »
More like too many bugs to keep track of... :-[
And lack of capable volunteers, I understand. Not sure if I can get my hands dirty to fix this myself, but let's see.

tennis

  • New Member
  • *
  • Posts: 11
Re: [Solved] Simple string loop
« Reply #10 on: July 16, 2020, 11:55:34 am »
Workaround posted by nanobit on bug tracker for anybody reading this:

Code: Pascal  [Select][+][-]
  1. // workaround with typecasting:
  2. type ta = array of string;
  3. var name : string;
  4. begin
  5. for name in ta(['project','customer','supplier']) do
  6. // or for name in [string('project'), string('customer'), string('supplier')] do
  7.     WriteLn(name);
  8. end.
  9.  

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: [Solved] Simple string loop
« Reply #11 on: July 16, 2020, 12:00:27 pm »
Dynamic array of string is predeclared in sysutils as https://www.freepascal.org/docs-html/rtl/sysutils/tstringarray.html

 

TinyPortal © 2005-2018