Hi GPC crew,
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)) Then SetLength(LocalS, P); ...
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". 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 run gpc 20050331 on gcc 3.4.3 under Sun Solaris 2.6
Thanks
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))
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
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
Pascal Viandier wrote:
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.
I don't know how to handle this.
Me neither. If I had a program to work with, I might be able to find out something. I don't do second-guessing anymore.
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).
Yes another reason for posting complete, tested, sample code, instead of made-up fragements ...
Frank
Ok, then.
I will try to solve this myself.
Thanks anyway.
Pascal pascal@accovia.com
Pascal Viandier wrote:
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.
I don't know how to handle this.
Me neither. If I had a program to work with, I might be able to find out something. I don't do second-guessing anymore.
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).
Yes another reason for posting complete, tested, sample code, instead of made-up fragements ...
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