Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-05

IE 200307043

19 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Aleksa Todorovic

Hi, all!

I've just tried to compile some of my old Pascal code, and got IE
200307043. I've tried both 2.2.4 and svn trunk versions. Simple program to generate it:

program test;
var
  p: Pointer;
begin
  p := nil + 1;
end.

I couldn't find issue about this in bug tracker, should I report it?

Best,
Aleksa

Joost van der Sluis
to Aleksa Todorovic: Hi, all! I've just tried to compile some of my old Pascal code, and got IE 200307043.…

Op zondag 24-05-2009 om 23:14 uur [tijdzone +0200], schreef Aleksa Todorovic:

Show quoted text 14 lines
Hi, all! I've just tried to compile some of my old Pascal code, and got IE 200307043. I've tried both 2.2.4 and svn trunk versions. Simple program to generate it: program test; var p: Pointer; begin p := nil + 1; end. I couldn't find issue about this in bug tracker, should I report it?

Yes, an IE is always a bug an should be reported. If you can not a report with '200307043' in it, it's not reported yet.

Joost.

Prince Riley
to Joost van der Sluis

Hello,

There seems to be a bigger issue on this... but perhaps someone else confirm that the following programs, similar to the failing one, work.

program test1;
  var
     p: Pointer;
  begin
    p := nil;
    p := p + 1;
end.

Does work .... and the following program

program test2;
   var
        p: Pointer;
   begin
        p := nil;
        Inc(p);
  end.

works also .... am I the only one getting this result?

Prince

Joost van der Sluis wrote 27 lines
Op zondag 24-05-2009 om 23:14 uur [tijdzone +0200], schreef Aleksa Todorovic: > Hi, all! > > I've just tried to compile some of my old Pascal code, and got IE > 200307043. I've tried both 2.2.4 and svn trunk versions. Simple > program to generate it: > > program test; > var > p: Pointer; > begin > p := nil + 1; > end. > > I couldn't find issue about this in bug tracker, should I report it? Yes, an IE is always a bug an should be reported. If you can not a report with '200307043' in it, it's not reported yet. Joost. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Jonas Maebe
to Prince Riley
Prince Riley wrote
There seems to be a bigger issue on this... but perhaps someone else confirm that the following programs, similar to the failing one, work.

That's because the error was in the constant evaluation (nil and 1 are both constants).

Jonas

Prince Riley
to Prince Riley: There seems to be a bigger issue on this... but perhaps someone else confirm that the…

Hello,

I had a chance to go to a reference and check on what the reserved word 'nil' , a special constant, seems to mean. According to the Object Pascal manual (Borland) ...

"The reserved word nil is a special constant that can be assigned to any pointer. When nil is assigned to a pointer, the pointer doesn't reference anything."

Since a pointer is a memory address value, then the interpretation of the statement "nil +1" would mean for p to point at the very next valid address above the lowest memory address 'p' can hold. So it would appear that 'p := nil + 1' should not compile or work.

My guess, and its just a guess, is that for 'nil + 1' to work then it would have to be done in two steps and not one, e.g. 'p := nil; p := p +1; ' .. both of which are valid statements. Now I have no idea what size address increment the compiler would choose (byte, word, float, etc.) to add to p. Perhaps it assumes PChar ..

But if that's not how it works, then my next question about the interpretation of 'p := nil + 1; ' is what is the 'size' of the 'p + 1' increment? How can that increment be set to without casting 'p' to a specific Pascal type (Integer, Char, Byte, Word, etc.).

So for Object Pascal the side effect of the statement 'p := nil +1' has to be valid address. As such the compiler does not know the type of object 'p' points at, it can't create a valid address.

On the other hand, untyped Pointers are a compromise in Object Pascal , a strongly typed language, to be similar to untyped pointer expressions like void * pointers in "C". Untyped C language pointers, according to K&R, represent the smallest unit of addressable memory for the CPU architecture (bytes on Intel).

However, even in C, the closest equivalent expression to 'p := nil + 1', void *p, is 'p = NULL, p = p + 1' works (compiles) but issues a warning about the 'p = p + 1' expression (GCC v4).

Prince Riley wrote 60 lines
Hello, There seems to be a bigger issue on this... but perhaps someone else confirm that the following programs, similar to the failing one, work. program test1; var p: Pointer; begin p := nil; p := p + 1; end. Does work .... and the following program program test2; var p: Pointer; begin p := nil; Inc(p); end. works also .... am I the only one getting this result? Prince On Sun, May 24, 2009 at 4:30 PM, Joost van der Sluis wrote: > Op zondag 24-05-2009 om 23:14 uur [tijdzone +0200], schreef Aleksa > Todorovic: > > Hi, all! > > > > I've just tried to compile some of my old Pascal code, and got IE > > 200307043. I've tried both 2.2.4 and svn trunk versions. Simple > > program to generate it: > > > > program test; > > var > > p: Pointer; > > begin > > p := nil + 1; > > end. > > > > I couldn't find issue about this in bug tracker, should I report it? > > Yes, an IE is always a bug an should be reported. If you can not a > report with '200307043' in it, it's not reported yet. > > Joost. > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal >
Prince Riley
to Jonas Maebe: That's because the error was in the constant evaluation (nil and 1 are both constants).…

Jonas,

Thanks for the reply.

That's a very interesting answer. So am I understanding you to say that the expression of the form

var := constant + numeric literal ;

is an invalid expression (syntax) in Object Pascal?

Why would the expression adding a numeric literal and a numeric constant create anything other than a numeric value? Both are assignment compatible with the pointer type, both have values known at compile time. True both have known values, but how does that change in the addition operation?

Both operands in the 'p := null + 1; expression' are constants that's true.
But isn't one a literal constant and in Object Pascal an expression of the
form: variable := constant + numeric literal is valid ?

Now I grant you an expression like 'a' + 1; would be invalid syntax; but in 'null + 1' there's only one constant and a numeric literal, not two. So unless I misunderstand you, or there's some run-time evaluation, shouldn't this expression be valid? (but I still worry about how the compiler would assign the correct type to the pointer (is it a valid address).

Jonas Maebe wrote 18 lines
On 25 May 2009, at 19:48, Prince Riley wrote: There seems to be a bigger issue on this... but perhaps someone else > confirm > that the following programs, similar to the failing one, work. > That's because the error was in the constant evaluation (nil and 1 are both constants). Jonas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Jonas Maebe
to Prince Riley
Prince Riley wrote 7 lines
That's a very interesting answer. So am I understanding you to say that the expression of the form var := constant + numeric literal ; is an invalid expression (syntax) in Object Pascal?

No, I meant that there was a bug (error) in the compiler regarding handling expressions of the form "nil + <integer constant>". It's a valid expression. nil has as type "pointer", and you can add integers to untyped pointers (constant or not). The result is again an untyped pointer.

Jonas

Prince Riley
to Jonas Maebe

Jonas

Thank you Jonas, for clearing that up. I agree.

You have more courage than I my friend to say that, for down that path lies monsters. For while I must agree with your point, in theory it raises a bigger concern.

The 'nil' for a pointer constant is problematic in two ways. Fixing this 'bug' could mean addressing two language issues. Type checking for valid pointer arithmetic and the difference between a 'null' or empty pointer and one that has the lowest value of it's type.

Both those points may sound abstract and esoteric, but they lie at the heart of the 'fix' for this bug. As you can surmise, for a strongly typed language like Object Pascal, pointer operations should be 'type safe' at best and 'type neutral' for flexibility and utility.

Even the apparently simple addition of numeric literal and a pointer requires considerable thought for reasons of portability and ensuring that pointer arithmetic doesn't become a source of opaque bugs.

Prince

Jonas Maebe wrote 24 lines
On 25 May 2009, at 22:39, Prince Riley wrote: That's a very interesting answer. So am I understanding you to say that > the > expression of the form > > var := constant + numeric literal ; > > is an invalid expression (syntax) in Object Pascal? > No, I meant that there was a bug (error) in the compiler regarding handling expressions of the form "nil + <integer constant>". It's a valid expression. nil has as type "pointer", and you can add integers to untyped pointers (constant or not). The result is again an untyped pointer. Jonas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
John Coppens
to Prince Riley
Type checking for valid pointer arithmetic and the difference between a 'null' or empty pointer and one that has the lowest value of it's type.

Maybe the use of 'nil' in an expression should not be allowed at all (except comparisons).

As I understand its meaning is that it sets (any) pointer to an invalid value. But I seem to have read that in case of microcontrollers 'NULL' at times means $FFFF, and, according to Wikipedia, some computers assign the max negative value to NULL:

http://en.wikipedia.org/wiki/Null_(computer_programming)

So, any reliance on nil being 0 (or any definite value) would seem unreliable (sorry for the pun).

Taking this further, nil = prt(0, 0) shouldn't be true (though in most programming languages they are equivalent, and in case of a PC-like environment it's complicated to represent a really 'invalid' scalar value).

John

Frank Peelo
to Prince Riley: I had a chance to go to a reference and check on what the reserved word 'nil' , a special…
Prince Riley wrote 13 lines
Hello, I had a chance to go to a reference and check on what the reserved word 'nil' , a special constant, seems to mean. According to the Object Pascal manual (Borland) ... "The reserved word nil is a special constant that can be assigned to any pointer. When nil is assigned to a pointer, the pointer doesn't reference anything." Since a pointer is a memory address value, then the interpretation of the statement "nil +1" would mean for p to point at the very next valid address above the lowest memory address 'p' can hold.

That is an "interesting" interpretation of "doesn't reference anything". There is no guarantee that nil is address 0, although it may be so in any available compiler -- at least, any compiler targetting an architecture that does not have usable memory at address 0. Nil doesn't 's an undefined address.

So it would appear that 'p := nil + 1' should not compile or work.

That would be reasonable - although if nil /was/ 0, then nil+1 would be defined for any given pointer type, and a compiler /could/ make a stab at compiling it -- but probably /should not/. Because what would "1 more than undefined" mean?

FP

Prince Riley
to Frank Peelo

Frank,

I think the crux of the matter here is how to make the distinction between a pointer with 'no value' and one that is initialized or set to the 'lowest possible value in the range'. The quote I mentioned comes directly from Borland's Object Pascal Langage Manual

You can check on this, but when I looked it up the 'nil' constant in a Object Pascal Language reference and what the reserved word 'nil' , a special constant, means in terms of pointer value (it's not an address) I was not able to find and what adding/subtracting/multiplying it by a literal numeric value (or another valid pointer value) to 'nil' would create.

If you're interested in the details (they are very instructive) compile a sample program with the two programs on an Intel based machine and then check the generated code with the GNU Debugger. Set a break point on the following statement

p := nil;

and then single step to the next instruction. You'll see immediately that two things happen: 1) the value assigned to 'p' by that statement is not a valid segment/offset address (i32/i64 architecture). If you then set another breakpoint on the next instruction,

p := p + 1;

you'll notice that the first thing that happens is 'p' get set to a valid segment address and then the offset, and not the base segment, is incremented by a value of '1' (again on a Intel CPU machine). Things get even more interesting when 'p' is first typed, to an Integer for example, and then assigned the 'nil' value. ....

 var
R:  Integer ;
P:  Pointer;
IntArray1, IntArray2: array of Integer;
IP:   ^Integer;
IntArrayPtr: Pointer;
begin
P := nil;
P := @R;
P := P + 1;
P := nil;
IntArray[0] := 1;
IntArray[1] := 1;
IP := @IntArray[0]
IP := IP + 1;
IntArrayPtr := @IntArray[1];
if  IntArrayPtr^  IP^ then Writeln ("Integer Array values not the same");
end.

Setting breakpoints on the statements where values are assigned to 'P' and 'IP' and watching how their values are set, incremented, and dereferenced will demonstrate how challenging even a simple pointer handling model can be.

Frank Peelo wrote 5 lines
Prince Riley wrote: > Hello, > >
Show quoted text 34 lines
> > "The reserved word nil is a special constant that can be assigned to any > pointer. When nil is assigned to a pointer, the pointer doesn't reference > anything." > > Since a pointer is a memory address value, then the interpretation of the > statement "nil +1" would mean for p to point at the very next valid address > above the lowest memory address 'p' can hold. > That is an "interesting" interpretation of "doesn't reference anything". There is no guarantee that nil is address 0, although it may be so in any available compiler -- at least, any compiler targetting an architecture that does not have usable memory at address 0. Nil doesn't point at anything. It's an undefined address. So it would appear that 'p := nil + 1' should not compile or work. > That would be reasonable - although if nil /was/ 0, then nil+1 would be defined for any given pointer type, and a compiler /could/ make a stab at compiling it -- but probably /should not/. Because what would "1 more than undefined" mean? FP _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Frank Peelo
to Prince Riley
Prince Riley wrote 7 lines
Frank, I think the crux of the matter here is how to make the distinction between a pointer with 'no value' and one that is initialized or set to the 'lowest possible value in the range'. The quote I mentioned comes directly from Borland's Object Pascal Langage Manual

"The reserved word nil is a special constant that can be assigned to any pointer. When nil is assigned to a pointer, the pointer doesn't reference anything."

I'm only quibbling with the equation of "doesn't reference anything" with "lowest possible value in the range". On many architectures, a pointer value of 0 might be a reasonable choice for "doesn't reference anything" because the CPU has interrupt vectors there, or uses address 0 for something else. But my point is that this is not guaranteed. Nil might not even point to valid data memory.

Show quoted text 6 lines
You can check on this, but when I looked it up the 'nil' constant in a Object Pascal Language reference and what the reserved word 'nil' , a special constant, means in terms of pointer value (it's not an address) I was not able to find and what adding/subtracting/multiplying it by a literal numeric value (or another valid pointer value) to 'nil' would create.

But I'm more puzzled by what it would /mean/. In spite of your bracketed comment here, you seem to be thinking that nil is an address: i.e. adding/subtracting/multiplying a literal would mean something. I'm just pointing out that, if you think it's an address, it's undefined. Because it's not any address. So adding something to it doesn't mean anything.

...

Show quoted text 8 lines
If you then set another breakpoint on the next instruction, p := p + 1; you'll notice that the first thing that happens is 'p' get set to a valid segment address and then the offset, and not the base segment, is incremented by a value of '1' (again on a Intel CPU machine).

Yup, GIGO.

FP

JoshyFun
to Frank Peelo

Hello Frank,

Wednesday, May 27, 2009, 2:49:26 PM, you wrote:

FP> But I'm more puzzled by what it would /mean/. In spite of your bracketed FP> comment here, you seem to be thinking that nil is an address: i.e. FP> adding/subtracting/multiplying a literal would mean something. I'm just FP> pointing out that, if you think it's an address, it's undefined. Because FP> it's not any address. So adding something to it doesn't mean anything.

From my point of view nil is like the infinite in mathematics, so it is not range bounded and operations like nil+1 are impossible, or in the worst case equal to nil again. Once you assigned nil to a pointer the value becomes in range so it can be operated as usual.

Best regards, JoshyFun
Jürgen Hestermann
to JoshyFun
From my point of view nil is like the infinite in mathematics, so it is not range bounded and operations like nil+1 are impossible, or in the worst case equal to nil again. Once you assigned nil to a pointer the value becomes in range so it can be operated as usual.

Yes, doing arithmetics with NIL is useless. NIL is defined to mean 'not defined'. How can you add something to that? Even if the compiler allows you to do that, the result cannot be predicted.

Jürgen Hestermann.

Frank Peelo
to JoshyFun: FP> But I'm more puzzled by what it would /mean/. In spite of your bracketed FP> comment…
JoshyFun wrote 14 lines
Hello Frank, Wednesday, May 27, 2009, 2:49:26 PM, you wrote: FP> But I'm more puzzled by what it would /mean/. In spite of your bracketed FP> comment here, you seem to be thinking that nil is an address: i.e. FP> adding/subtracting/multiplying a literal would mean something. I'm just FP> pointing out that, if you think it's an address, it's undefined. Because FP> it's not any address. So adding something to it doesn't mean anything. From my point of view nil is like the infinite in mathematics, so it is not range bounded and operations like nil+1 are impossible, or in the worst case equal to nil again. Once you assigned nil to a pointer the value becomes in range so it can be operated as usual.

Thanks. That's what I was trying to get across. Why try nil+1? It doesn't mean anything! So the Error is only that a different error message should appear - not that it should compile.

FP

Prince Riley
to Frank Peelo: "The reserved word nil is a special constant that can be assigned to any pointer. When…

Hello Frank,

If my past post was unclear as to whether I think the constant 'nil' is an address, then let me be clear. I quoted the Borland Object Pascal's statement nil 'does not reference anything' I was not equating it to a zero address value. While a pointer with a 'zero' address value should be invalid, it is different from a pointer with a value of 'nil.'

FP uses the special address constant, 'nil' in much the same way. If you assign a pointer a valid address and perform valid operations on it, say you repeatedly decrement or shift it (arithmetic) you could produce an invalid address. But it would not be 'nil'.

Nil is, by definition, an address; albiet, a special one like the mathmatical set theory concept of 'empty or null set'. Nil is defined as a 'meta value' and as such whatever the lowest address value in the range of addresses actually is, nil is defined not a member of that set.

The distinction between a valid address expression that has 'nil' as an operand and an invalid one (decrementing or shifting a pointer outside a valid address range) however raises a related by seperate issue. FP must have operators like assignment or comparision that allow 'nil' to be used in an expression.

The 'value' such an expression has must be defined in some way just as nil is a defined lanuage constant; a way that consistently signals ('represents') the expression or operation produces an invalid result. So in the example given there are two possible decisions

p := p + nil;   is INVALID (expression is valid, operands valid but result
is invalid) -- execution error, execution addressing exception

or

p := p + nil; is UNDEFINED (expression is invalid, no operation, no result)
-- compiler error

The second case is what FP does when nil is used in an expression . The ultimate problem lies in the first case, how to implement nil in a consistent and reliable way as a internal binary value.

In K&R, for example, the NULL address pointer is 'defined' but is implemented in several different ways based on target CPU. If you look at C program startup library code you'll see that. The NULL address value in 'C' was defined for several years a binary '0' on VAX, and PDP machines. This allowed tests for invalid or empty pointers using the compact syntatic expression ' if (p) {...}'

Likewise, (p = NULL; and p == NULL) in C are both valid expressions neither result in compiler warnings or errors (in strict compilers they do) But there is a difference between how they operate on the expression (p = NULL + p) and (p = 0 + p) which is similar to the case we are talking abotu here.

So here is our questiuon: should FP allow the expression (p := nil + p)? If so, what should the result be? I opt that FP should treat it as an invalid expression (compile error) and not as a valid expression with an UNDEFINED value. I realize that this differs from what others might think or suggest.

Frank Peelo wrote 56 lines
Prince Riley wrote: > > Frank, > > I think the crux of the matter here is how to make the distinction between > a pointer with 'no value' and one that is initialized or set to the 'lowest > possible value in the range'. The quote I mentioned comes directly from > Borland's Object Pascal Langage Manual > "The reserved word nil is a special constant that can be assigned to any pointer. When nil is assigned to a pointer, the pointer doesn't reference anything." I'm only quibbling with the equation of "doesn't reference anything" with "lowest possible value in the range". On many architectures, a pointer value of 0 might be a reasonable choice for "doesn't reference anything" because the CPU has interrupt vectors there, or uses address 0 for something else. But my point is that this is not guaranteed. Nil might not even point to valid data memory. You can check on this, but when I looked it up the 'nil' constant in a > Object Pascal Language reference and what the reserved word 'nil' , a > special constant, means in terms of pointer value (it's not an address) I > was not able to find and what adding/subtracting/multiplying it by a > literal numeric value (or another valid pointer value) to 'nil' would > create. > But I'm more puzzled by what it would /mean/. In spite of your bracketed comment here, you seem to be thinking that nil is an address: i.e. adding/subtracting/multiplying a literal would mean something. I'm just pointing out that, if you think it's an address, it's undefined. Because it's not any address. So adding something to it doesn't mean anything. ... > If you then set another breakpoint on the next instruction, > p := p + 1; > > you'll notice that the first thing that happens is 'p' get set to a valid > segment address and then the offset, and not the base segment, is > incremented by a value of '1' (again on a Intel CPU machine). > Yup, GIGO. FP _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Jonas Maebe
to Prince Riley
Prince Riley wrote
p := p + nil; is INVALID (expression is valid, operands valid but result is invalid) -- execution error, execution addressing exception

This will always be invalid regardless of how nil is handled, because you cannot add two pointers together. You can add integers to pointers though, so the question is about "nil + 1" and the like. Delphi indeed gives an error, which makes sense. I resolved the internalerror by accepting the expression, which is indeed not a good idea. So I'll change it.

Jonas

Frank Peelo
to Prince Riley: If my past post was unclear as to whether I think the constant 'nil' is an address,…
Prince Riley wrote 7 lines
Hello Frank, If my past post was unclear as to whether I think the constant 'nil' is an address, then let me be clear. I quoted the Borland Object Pascal's statement nil 'does not reference anything' I was not equating it to a zero address value. While a pointer with a 'zero' address value should be invalid, it is different from a pointer with a value of 'nil.'

Agreement.

...

Show quoted text 5 lines
The distinction between a valid address expression that has 'nil' as an operand and an invalid one (decrementing or shifting a pointer outside a valid address range) however raises a related by seperate issue. FP must have operators like assignment or comparision that allow 'nil' to be used in an expression.

Assignment and comparison, yes. But arithmetic expressions such as nil+1 do not make sense; if the compiler allows them, that must be by accident.

The second case is what FP does when nil is used in an expression . The ultimate problem lies in the first case, how to implement nil in a consistent and reliable way as a internal binary value.

Yes. The compiler makers can choose any value that does not represent valid usable memory.

Show quoted text 6 lines
In K&R, for example, the NULL address pointer is 'defined' but is implemented in several different ways based on target CPU. If you look at C program startup library code you'll see that. The NULL address value in 'C' was defined for several years a binary '0' on VAX, and PDP machines. This allowed tests for invalid or empty pointers using the compact syntatic expression ' if (p) {...}'

That is still done. In fact, in C++, 0 is a valid representation for the NULL value; if the internal representation of NULL is not 0, the compiler or library has to fake it.

But FPC is not C++.

Likewise, (p = NULL; and p == NULL) in C are both valid expressions neither result in compiler warnings or errors (in strict compilers they do)

They shouldn't. The first assigns the NULL value to a pointer. The second compares a pointer with NULL. That's all perfectly legal.

But there is a difference between how they operate on the expression (p = NULL + p) and (p = 0 + p) which is similar to the case we are talking abotu here.

Not really. Adding an integer to a pointer to the start of an array, gives you a pointer to an element in that array. So 0+p is legal. But if NULL is ((void)0), which is more common in C nowadays and is closer to Nil in that it is explicitly a pointer, then NULL+p is not legal.

And you had been talking about Nil+1, not Nil+p.

So here is our questiuon: should FP allow the expression (p := nil + p)?

Not for me to say, but I would expect it should not.

Frank