Prof Abimbola Olowofoyeku wrote:
On 17 Mar 2002 at 13:16, Martin Liddle wrote:
I have just moved to RC 3. Looking at the list of fixed bugs it is obvious that a lot of work has been done in the last few months; thanks to all concerned. The stricter type checking required a lot of effort to get our code to compile but in fairness did highlight a number of problems in our code; so I think it was time well spent. However I am now stuck because of the following problem:
Program WriteTest;
Procedure ZWriteln(AString:String); Begin AString:=AString+'ML'; Writeln('String [',AString,'] Length is ',Length(AString)); End;
Begin ZWriteln(' '); End.
What I see is that length is reported as 1 i.e. the string concatenation is failing. Is this expected behaviour or a bug?
It is a bug alright. If you pass a string variable rather than a literal to 'ZWriteln', the concatentation is successful. So, something seems to have gone awry somewhere.
No, it's not a bug. `AString' is a formal parameter of undiscriminated schema type. This means it assumes the discriminants (in case of String: Capacity) of the actual parameter. In the example, the actual parameter is a string constant of length 1. It also has capacity 1, since constants can't change, anyway.
So also the parameter has capacity 1 during the execution of `ZWriteln'. Assigning ` ML' (the result of concatenation) to a capacity 1 string results in truncation to ` '. This behaviour is not new, BTW.
As a rule of thumb, the problem generally might show when you have value parameters of type `String' and you extend their length in the routine. (Var parameters are not affected since you can't pass constants to them, anyway, and const/protected parameters are safe because they can't be changed in the routine. Discriminated string parameters are no problem provided the declared capacity is big enough. Shortening the parameters, or modifying them with the same length is also no problem, obviously.)
So, one solution here is to declare `AString' with a capacity (e.g., of type `TString' if you use the GPC unit). This will work if you know a constant bound on the capacity (e.g., 255 for those used to BP ;-). If that's not the case, something like the following might help (e.g., if you know the the string will not be enlarged by more than 2 characters):
Procedure ZWriteln(AString:String); var LocalAString: String (Length (AString) + 2); Begin LocalAString:=AString+'ML'; Writeln('String [',LocalAString,'] Length is ',Length(LocalAString)); End;
I also note that trying to set the Capacity of a string schema is now flagged as an error.
My understanding that it should always have been flagged as an error.
Indeed.
Is there an "official" way to set the capacity? We were only setting the capacity as a workaround for problems in previous versions of gpc where under various circumstances it wasn't initialised properly. My first stab is to comment out all the places where we were setting capacity but I can't test if everything is OK because of the problem noted above.
'SetLength' should work. However, I am not sure that you can use it for increasing (as opposed to decreasing) the maximum length of a string.
`SetLength' is for setting the (current) length, not the Capacity (= maximum length). The Capacity cannot be changed reasonably because it would apparently change the size of the variable.
If you still need the workarounds, let me know, so I can try to fix the problems and/or give you an advice how to adapt the workaround.
Frank