Recent

Author Topic: [SOLVED] Strange result (to me) from FillChar()  (Read 278 times)

tfurnivall

  • New Member
  • *
  • Posts: 49
[SOLVED] Strange result (to me) from FillChar()
« on: June 21, 2025, 06:37:58 pm »
I'm trying to get an 18-character space string to pre-pend to a header line> Looking up what's available, I found FillChar():
Quote
Program Example25;

{ Program to demonstrate the FillChar function. }

Var S : String[10];
    I : Byte;
begin
  For i:=10 downto 0 do
    begin
    { Fill S with i spaces }
    FillChar (S,SizeOf(S),' ');
    { Set Length }
    SetLength(S,I);
    Writeln (s,'*');
    end;
end.

The example had me scratching my head, because it seems to avoid using FillChar to do what FillChar is advertised as doing, but, at any rate, I took the example as offered, and used it in my code:
Code: Pascal  [Select][+][-]
  1.   FillChar (ListHeaderA, sizeof(ListHeaderA),' ');
  2.   SetLength(ListHeaderA,18);
  3.   FillChar (ListHeaderB, sizeof(ListHeaderB),' ');
  4.   SetLength(ListHeaderB,18);
  5.  

My understanding is that the 18 bytes at ListHeaderA are filled with ' ', which means that the string (ListHeaderA) has an apparent length of 32 (the value of ' '). So I used SetLength, as in the example, to set the length to 18.

When I try to run the program, which compiles cleanly because, as the documentation says, no checking is done on the target of FillChar(), I get an address violation at $FFFFFFFFFFFFFFFF, at address 10008F1A.

Clearly something is wrong (and I don't like being able to wipe out the length of a string just like that).

Should I:

1)  Use ListHeaderA[1] as the parameter to FillChar        - gives Access VIolation one line earlier!
2)  Copy the example and fill each byte individually (backwards (???)
3)  Drop sizeof(ListHeaderA) etc and simply use 18        - gives Access Violation in the original line.
4) Try some other way of doing this (it's only done once, and I don't mind adding 18 spaces to an empty string. I just wanted to try FillChar.

Any enlightenment?

Please,

Tony
« Last Edit: June 21, 2025, 11:24:27 pm by tfurnivall »

Thaddy

  • Hero Member
  • *****
  • Posts: 17476
  • Ceterum censeo Trumpum esse delendum (Tnx Charlie)
Re: Strange result (to me) from FillChar()
« Reply #1 on: June 21, 2025, 07:17:43 pm »
Code: Pascal  [Select][+][-]
  1. {$H-}// shortstrings
  2. var
  3.   s:string;
  4. begin
  5.   s:=StringOfChar(#32,18);// from system. #32 is a space. s is COW.
  6. // or  fillchar(s,18,#32); if you want. But only if the shortstring already has length 18.
  7. // Fillchar is not copy on write (COW) whereas StringOfChar is...
  8.   writeln(s);
  9. end.

The mistake you make is s:string[10] which limits the size to 10 and the compiler sticks to that.
« Last Edit: June 21, 2025, 07:30:20 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

jamie

  • Hero Member
  • *****
  • Posts: 6995
Re: Strange result (to me) from FillChar()
« Reply #2 on: June 21, 2025, 07:28:38 pm »
If you are using short strings, those with predermined length in the variable section, the first index of 0 is used as the length of the remainder.

 So, if you have a string[[10], the actual size is 11 however,If you want to use SizeOf(TheShortString), you must subtract 1 and start with the index of 1.

Fillchar(MyString[1],Sizeof(MyString)-1,' ');

 You can use a managed Ansistring if you have {$H+} indicated at the top of your code and use other methods to created a blank string of whatever char you want, like the StringOFchar which will create an ansistring on its return.

 If you don't use the {$H+} at the top, then a string with no length set at definition time will be 255 bytes of character storage space.

Jamie


The only true wisdom is knowing you know nothing

tfurnivall

  • New Member
  • *
  • Posts: 49
Re: Strange result (to me) from FillChar()
« Reply #3 on: June 21, 2025, 11:24:05 pm »
Thanks for the guidance from the usual suspects ;)

I ended up just concatenating 18 spaces. It's in an initialization routine, and the effort was minimal.

In the example I cited, I defined ListHeaderA and ListHeaderB as plain string - which I guess moves them into the heap, and allows them to grow to gargantuan size. But they still have a location. Hmm, and the length is now 4 bytes? Or 8 bytes if we want to get into the heap? (All depending, of course, how Lazarus sets up a heap pointer rather than a stack pointer).

I suppose (gripe alert) that it's really up to the people who wrote the example code to document and explain very clearly why they are doing what they are doing.

Nope, I don't do nearly enough of that, myself,  but when I do, I find that my understanding increases as well!


 

TinyPortal © 2005-2018