Sign in Join

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

Mailing lists / fpc-devel / 2019-11

Capturing addresses

6 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Jonas Maebe

Hi,

Does anyone know what the accepted/excepted behaviour is regarding the capture of addresses of var/out/const-by-address/constref parameters?

For example:

var
  g: longint;
  p: plongint;
procedure test(var l: longint);
begin
  ;
end;
begin
  test(g);
end.

After test() executes, p now contains the address of g (the '@' operator does not return the address of g's address on the stack; it returns the actual address of g). This means that g's address has been captured by test(). This can obviously lead to wrong/dangerous situations, e.g. if g was not a global variable, but a local variable of another procedure. That said, it is a legal expression.

I would like to teach the compiler to be able to assume that addresses of variables are not captured merely because they are passed by reference. There will also be a switch to toggle this assumption, because fortunately it the behaviour is completely defined by the callee side (so if you know that a unit does this, compiling that unit appropriately is sufficient to ensure it will always work correctly).

The question is: should the compiler by default assume that such addresses are not captured, or that they are captured? Does anyone know if a lot of code exists that does this?

Jonas

Reply by email

Martin Frb
to Jonas Maebe
Jonas Maebe wrote 22 lines
For example: var g: longint; p: plongint; procedure test(var l: longint); begin ; end; begin test(g); end. After test() executes, p now contains the address of g (the '@' operator does not return the address of g's address on the stack; it returns the actual address of g). This means that g's address has been captured by test(). This can obviously lead to wrong/dangerous situations, e.g. if g was not a global variable, but a local variable of another procedure. That said, it is a legal expression.

Your example shows the safe case (p is and will continue to be safe).

In the unsafe case (g to be a local var), this is similar to none "var param"

var
   p: plongint;
procedure test(l: longint);
begin
   ;
end;

p will be a dangling pointer, after "test" exited. The same as in your example, but with the case that "g" is local, p becomes dangling when "g" goes out of scope.

So I am trying to understand what the difference (in terms of safety) is? (except that the none "var param" is always unsafe, the "var param" is only sometimes unsafe)?

Also out of interest, what would change if you ...

teach the compiler to be able to assume that addresses of variables are not captured merely because they are passed by reference

Reply by email

Jonas Maebe
to Martin Frb
Martin Frb wrote
So I am trying to understand what the difference (in terms of safety) is? (except that the none "var param" is always unsafe, the "var param" is only sometimes unsafe)?

If you are talking about the safety of accesses after the capturing routine has exited, then that is indeed the only difference.

Also out of interest, what would change if you ... > teach the compiler to be able to assume that addresses > of variables are not captured merely because they are passed by > reference

It should allow the compiler to get rid of a lot of temporary function results (and copying those temporary results to their final destination), in particular for shortstring and set operations, and for overloaded operators that work with records.

Jonas

Reply by email

Martin Frb
to Jonas Maebe
Jonas Maebe wrote 7 lines
On 10/11/2019 14:58, Martin Frb wrote: > So I am trying to understand what the difference (in terms of safety) > is? (except that the none "var param" is always unsafe, the "var param" > is only sometimes unsafe)? If you are talking about the safety of accesses after the capturing routine has exited, then that is indeed the only difference.

Ok then I am missing some (maybe internal?) detail. Not to important, just curiosity.

Reply by email

Marco Borsari
to Jonas Maebe: Does anyone know what the accepted/excepted behaviour is regarding the capture of…

Il 10/11/2019 14:36, Jonas Maebe ha scritto:

Show quoted text 23 lines
Hi, Does anyone know what the accepted/excepted behaviour is regarding the capture of addresses of var/out/const-by-address/constref parameters? For example: var g: longint; p: plongint; procedure test(var l: longint); begin ; end; begin test(g); end. The question is: should the compiler by default assume that such addresses are not captured, or that they are captured? Does anyone know if a lot of code exists that does this?

To me should be simply refused by the compiler as it happens in case of p:=l.
Marco

Reply by email

Marc Weustink
to Jonas Maebe: Does anyone know what the accepted/excepted behaviour is regarding the capture of…
Jonas Maebe wrote 37 lines
Hi, Does anyone know what the accepted/excepted behaviour is regarding the capture of addresses of var/out/const-by-address/constref parameters? For example: var g: longint; p: plongint; procedure test(var l: longint); begin ; end; begin test(g); end. After test() executes, p now contains the address of g (the '@' operator does not return the address of g's address on the stack; it returns the actual address of g). This means that g's address has been captured by test(). This can obviously lead to wrong/dangerous situations, e.g. if g was not a global variable, but a local variable of another procedure. That said, it is a legal expression. I would like to teach the compiler to be able to assume that addresses of variables are not captured merely because they are passed by reference. There will also be a switch to toggle this assumption, because fortunately it the behaviour is completely defined by the callee side (so if you know that a unit does this, compiling that unit appropriately is sufficient to ensure it will always work correctly). The question is: should the compiler by default assume that such addresses are not captured, or that they are captured? Does anyone know if a lot of code exists that does this?

I've a lot of (interfacing) code where the address of a var is used, where the resulting pointer used locally. I don't think I've code which stores that pointer somewhere outside the procedure.

Marc

Reply by email