New GPC beta: gpc-971001_(re)

Sat, 11 Oct 1997 01:23:15 +0200



The African Chief wrote:

> >Secondly, you copy back the old value of s back afterwards. This only works
> >because GPC copies only Length(x) characters. If this behaviour would be
> >changed to copy more characters (of course not more than x.Capacity), your
> >code would break. (Such a change might be done for efficiency, e.g. by
> >rounding up to a multiple of 4, and though I don't think it's likely to
> >be changed, the change would be valid,
>
> I disagree that it would be valid.
>
> >AFAIK, since the characters after Length(x) in a string are undefined.)
>
> Which is why you should  only copy to length(s).

You probably should, but (AFAIK) you don't have to.

> If I do "str1 := str2" , I do not expect an optimiser to make it into;
> "str1 := str2 + any junk after the length of str2, up till str2.capacity".

Not "str2 + any junk", it's still only "str2", according to the definition
of (this kind of) strings. Generally, a string always contains "junk" after
the length till the capacity, and you shouldn't rely on anything about this
junk. (E.g., I recently modified the WriteStr procedure so that it will
not fill a (normal) string with spaces, #0's or whatever as it did before.
Only arrays of char are padded with spaces, unless treated as CStrings.
I don't think such a change should matter to any "good" program.)

> >A possible "fix" for the second problem (not the first one, though the
> >appearance of the problem will be different then) would be
> >"s[Length(s)+1]:=#0" (also, it's much more efficient).
>
> I am not sure how this solves the problem.

When you explicitly write a #0 into the "junk" area, you can be sure that
it will be there (because you don't use any string functions, such as
assignments between strings). And it's more efficient because you don't
have to copy the contents of the string (twice) and don't need any temp
variables. Therefore, you don't have to limit the length of the string
(in system.pas it's limited to 255 chars).

> That will be good. The compiler can better cater for some things. However,
> I have a version of Str2pChar which deals with this bug, but it would require
> the user to dispose of memory afterwards - which means it cannot be used
> in an expression (which is what I want it for). I have added this version to
> system.pas, but commented it out. I have also noted the "full length string bug"
> in the sources.  This is the fixed version, which seems to work okay. Any
> comments?

Allocating memory and copying the string seems to be the only way possible
in Pascal code that really solves all problems. (Including a third one,
namely that the resulting CString isn't influenced by modifications of the
Pascal string, as one would expect from a function result. However, I guess
this is seldom a real problem because of the way the function is used
usually.)

Actually, for sometime later we have planned to build the following functions
into the compiler:

- One that just appends the #0 and returns the addres of the first character
  of the string (solves problem 2; not 3; problem 1 will be solved by making
  strings internally bigger than declared by 1 char). For short strings (when
  they will be introduced), this function will make a temporary copy on the
  stack (because they must be BP compatible so there will not always be space
  for the #0 in the string).

- One that always makes a copy on the stack and copies the string into it.
  That's the secure way, but inefficient with very long strings.

- One that allocates the memory on the heap. This is needed when the
  resulting CString is to be used outside of the current scope (when it's
  not only passed to a function).

- One that copies the string in a buffer allocated by the programmer (this
  is perhaps only for compatibility with BP's StrPCopy).

(* Peter, was this what we intended to do, or did I confuse anything? ;*)

> program x;
>
> uses
> strings;
>
> Function Str2pChar ( s : String ) : pChar;
> Begin
>   Str2pChar := StrNew ( StrCopy ( @s [1], @s[1] ) );

I don't understand this line. What do you expect "StrCopy ( @s [1], @s[1] )"
to do? AFAICS, it copies a string into itself!? I assume it's meant to add
a #0 terminator, but I fail to see how it would do this (unless there is
already a #0 somewhere)...

OTOH, if you're using the strings unit anyway, is there anything wrong with
StrPCopy?

> End; {* str2pChar *}
>
> const
>   s:string='                                                   '+
>            '                                                   '+
>            '                                                   '+
>            '                                                   '+
>            '                              '#13#10'This program is OK.';
> 
>   t:string=#8#8#8#8' wrong, sorry.'#0;
>
> var
> p:pchar;
> begin
>   p:=str2pchar(s);
>   writeln(p);
>   StrDispose(p);  { need to dispose of the memory! }
> end.

This program does not work correctly in my BP. It might seem to work for you
because you pass s by value now, so now there will not be t after s in memory
(on the stack), but something else.

> BTW:
> "const t:string=#8#8#8#8' wrong, sorry.'#0;" doesn't compile
> under GPC !

Peter Gerwinski wrote:

> It does under my version of gpc-971001, under DJGPP as well as
> under Linux.

On mine, it works, too, but only once! The program:

program x;
const t1:string(255)=#8#8#8#8' wrong, sorry.'#0;
const t2:string(255)=#8#8#8#8' wrong, sorry.'#0;
begin
end.

gives the error:

y.p:3: numeric constant contains digits beyond the radix
    ^
for the second(!) declaration. Now, that's strange...

Anyway, it seems to be realted to the problem reported in
<6dRwLb2VlJB@rufus.central.de>.

--
Frank Heckenbach, Erlangen, Germany
heckenb@mi.uni-erlangen.de
http://home.pages.de/~fjf/links.htm


Frank Heckenbach (heckenb@mi.uni-erlangen.de)

HTML conversion by Lluís de Yzaguirre i Maura
Institut de Lingüística Aplicada - Universitat "Pompeu Fabra"
e-mail: de_yza@upf.es