Hi Frank,
When trying to write a sample program to illustrate the problem, I become more confused than before. It seems to be more complicated than I thought.
First, I was somewhat wrong from the start. In fact, it looks like Length() may be the source of the problem.
In the procedure, I declared an Integer variable L to store the length of LocalS.
Now, the procedure looks like this:
Procedure CleanZeroesAndDisplay(Const S: String); Var LocalS : String(40) = S; P : Integer; L : Integer; Begin P := Pos(Chr(0), LocalS); L := Length(LocalS); If (P > 0 And P < Length(LocalS)) Then SetLength(LocalS, P - 1); ...
If I execute it with a parameter like this: LocalS dump in decimal is 00 00 00 40 00 00 00 40 85 84 73 76 00 00 00 00 ...
That is a capacity of 40, a length of 40 and the contents 'UTIL' plus 36 Chr(0)
In my real-life program, if I step through it with gdb L, the result of Length(LocalStr) is 40. With the same code (copy/paste) in the sample program, Length(LocalStr) returns 4 so the behaviour is not the same.
I compile and link both programs with -O0 and -g command-line options to have the most of the debugging info.
I don't know how to handle this.
Pascal Viandier pascal@accovia.com
Pascal Viandier wrote:
I encounter a problem with SetLength: I have a string of 40 characters long coming from a file (no control on
it).
On these 40 characters the first 13 are "meaningfull" and the others are Chr(0). The String as I can see it through gdb indicates a capacity of 40, a
length
of 40 and the contents as explained. I want to get rid of the Chr(0) by setting the actual string length to
the
meaningful part (13). So the following code should do this in a clean way (I think):
Procedure CleanZeroesAndDisplay(Const S: String); Var LocalS : String(40) = S; P : Integer; Begin P := Pos(Chr(0), LocalS); If (P > 0 And P < Length(LocalS))
Wrong parentheses. What you probably mean is this:
If (P > 0) And (P < Length(LocalS))
It was a typo in the email, not in the code (I re-typed it manually).
Then SetLength(LocalS, P);
Here you probably want P - 1, though this doesn't seem to be the main problem.
End;
When executing this code with the previous example, P returns 13,
Length(S)
returns 40 so I enter the "If" and SetLength is called. The problem is that after the call I see that the actual length of
LocalS
still 40. The debugging is somewhat approximate since I can enter the "Pos"
function
with gdb but not "SetLength".
Yes, SetLength is expanded to inline code by the compiler. There exists no such (linker-level) function which gdb could call.
Even better, if I replace the SetLength call by LocalS := Copy(LocalS,
1,
P); it does not work either (the length stays 40).
I don't know if the presence of Chr(0) makes the functions behave erratically but the following code solves the problem in a somewhat
dirty
and strange way:
Procedure CleanZeroes(Const S: String); Var LocalS : String(40) = S; P : Integer; Begin P := Pos(Chr(0), LocalS); If (P > 0 And P < Length(LocalS)) Then FillChar(LocalS[P], (Length(LocalS) -P) + 1, ' '); ...
End;
The "strange" part (for me :-) is that the call to the "Fillchar
monster",
fills (replace) the string's contents as expected AND sets the actual
length
of the string to 13, as if I called Trim! I am somewhat confused on what is going on there. May this be a bug?
I'm also a bit confused. If it's not the parentheses problem (as above), can you please post some code to reproduce the problem (which means complete programs, for both cases)?
Frank
-- Frank Heckenbach, frank@g-n-u.de, http://fjf.gnu.de/, 7977168E GPC To-Do list, latest features, fixed bugs: http://www.gnu-pascal.de/todo.html GPC download signing key: ACB3 79B2 7EB2 B7A7 EFDE D101 CD02 4C9D 0FE0 E5E8