Recent

Author Topic: var absolute anyone?  (Read 3395 times)

EganSolo

  • Sr. Member
  • ****
  • Posts: 398
var absolute anyone?
« on: October 03, 2021, 10:45:21 am »
Over the years, I've been discouraged from declaring variables with the absolute directive as in
Code: Pascal  [Select][+][-]
  1. function SortByIndex(Item1, Item2: Pointer): integer;
  2. //Asume that Tmyobject has a property Val which is integer.
  3. var o1 : TMyObject absolute Item1;
  4.     o2 : TMyObject absolute Item2;
  5. begin
  6.   Result := o1.Val - o2.Val;
  7. end;
  8.  

I know that _in general_ absolute could open a can of worms but in this context, where you are guaranteed that the variables and the params are sharing the same mem block, what would be the drawback to use absolute? It strikes me as a more elegant way than having to assign and typecast the params.

Thoughts?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12894
  • FPC developer.
Re: var absolute anyone?
« Reply #1 on: October 03, 2021, 10:47:53 am »
You have two symbols (the param and the var declaration) that are differently typed pointing to the same memory   With automated types that could give trouble.

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1071
Re: var absolute anyone?
« Reply #2 on: October 03, 2021, 12:39:03 pm »
Or in general: it removes all type checking. Even if the type of Item1 and Item2 were changed to byte, it would still compile without any problems.

jamie

  • Hero Member
  • *****
  • Posts: 7760
Re: var absolute anyone?
« Reply #3 on: October 03, 2021, 02:36:38 pm »
I love type-less parameters, things can really go wild that but it also allows for major flex with the code, too!.

name(Var someParam;, ,,,,,);


But really, a variant record can achieve the same results with a more controlled outcome.
The only true wisdom is knowing you know nothing

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: var absolute anyone?
« Reply #4 on: October 03, 2021, 04:40:34 pm »
The example you presented (sort functions) is a perfect place for this usage. You are forced to use pointers while the actual type is TMyObject.

EganSolo

  • Sr. Member
  • ****
  • Posts: 398
Re: var absolute anyone?
« Reply #5 on: October 03, 2021, 09:16:46 pm »
Thank you, everyone, for your comments!
I completely agree that typeless params are dangerous. Actually, they're a bit of an anti-pattern in Pascal  :D which is why I tend not to use them.

Variant records are indeed more controlled, but as far as the Use Case I presented, Engkin expressed my thought perfectly. That's pretty much the only place where I believe absolute is justified: the signature of the sort function has not changed in ages, therefore, in this case, the risk is low.

Appreciate all of your comments!

Warfley

  • Hero Member
  • *****
  • Posts: 2066
Re: var absolute anyone?
« Reply #6 on: October 03, 2021, 10:00:42 pm »
I would not use var absolute in this case, but rather the following:
Code: Pascal  [Select][+][-]
  1.     function SortByIndex(Item1, Item2: Pointer): integer;
  2.     //Asume that Tmyobject has a property Val which is integer.
  3.     var o1 : TMyObject;
  4.         o2 : TMyObject;
  5.     begin
  6.       o1 := TMyObject(Item1);
  7.       o2 := TMyObject(Item2);
  8.       Result := o1.Val - o2.Val;
  9.     end;
  10.      
The optimizer should make sure that this is in no way less efficient, but it has the advantage that the compiler ensures that typecasting between the type of Item1 and o1 is allowed.

But I would even go further:
Code: Pascal  [Select][+][-]
  1.     function SortByIndex(Item1, Item2: Pointer): integer;
  2.     //Asume that Tmyobject has a property Val which is integer.
  3.     var o1 : TMyObject;
  4.         o2 : TMyObject;
  5.     begin
  6.       o1 := TObject(Item1) as TMyObject;
  7.       o2 := TObject(Item2) as TMyObject;
  8.       Result := o1.Val - o2.Val;
  9.     end;
This also adds runtime error checking if the parameters are actually of that type

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1071
Re: var absolute anyone?
« Reply #7 on: October 03, 2021, 10:02:25 pm »
I would not use var absolute in this case, but rather the following:
The compiler transforms the first version into the second version when compiling with -CR.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: var absolute anyone?
« Reply #8 on: October 03, 2021, 11:00:14 pm »
I would not use var absolute in this case, but rather the following:
...
But I would even go further:
...
This also adds runtime error checking if the parameters are actually of that type

In this case? Even when you already know the parameters are of type TMyObject?

Warfley

  • Hero Member
  • *****
  • Posts: 2066
Re: var absolute anyone?
« Reply #9 on: October 04, 2021, 01:12:07 am »
In this case? Even when you already know the parameters are of type TMyObject?
Yes because code is constantly evolving and assumptions that are true at the time of writing might not be in the future. And I always want to get as many warnings and errors as possible to verify if my assumptions are not valid anymore.
I want my compiler to verify as much as possible.

Also by using casts, you can also make use of transparent type conversions. E.g. if you use a custom allocator that internally uses an array, you might rather than giving a pointer, give a refernece to that array and an offset/index within that array. You could create a record type for this, and override the cast to TObject for this and this would make it possible to make use of this new allocator transparently without having to change a single line of code anywhere else.
Or, something that I actually have used in the past, on X64 systems pointer only use 48 bits of their 64 bits, meaning you can encode additional information in the other bits (I used this for polymorphism to identify the type). There an overloaded cast can be used to extract the pointer bits to make it usable for dereferencing.
With absolute this doesn't work because it circumvents the cast.
« Last Edit: October 04, 2021, 01:25:24 am by Warfley »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: var absolute anyone?
« Reply #10 on: October 04, 2021, 07:44:57 am »
In this case? Even when you already know the parameters are of type TMyObject?
Yes because code is constantly evolving and assumptions that are true at the time of writing might not be in the future. And I always want to get as many warnings and errors as possible to verify if my assumptions are not valid anymore.
I want my compiler to verify as much as possible.

The compiler will not do any verification when you use typecasts. Try:
Code: Pascal  [Select][+][-]
  1. var
  2.   p:pointer=pointer($1122334455667788);
  3.   sl:TStringList;
  4.   c: Integer;
  5. begin
  6.   sl:=TStringList(p);
  7.   c:=sl.Count;
  8.   WriteLn('c: ',c);  

Compare it to:
Code: Pascal  [Select][+][-]
  1. var
  2.   p:pointer=pointer($1122334455667788);
  3.   sl:TStringList absolute p;
  4.   c: Integer;
  5. begin
  6.   c:=sl.Count;
  7.   WriteLn('c: ',c);  

PascalDragon

  • Hero Member
  • *****
  • Posts: 6396
  • Compiler Developer
Re: var absolute anyone?
« Reply #11 on: October 04, 2021, 09:02:56 am »
Over the years, I've been discouraged from declaring variables with the absolute directive as in
Code: Pascal  [Select][+][-]
  1. function SortByIndex(Item1, Item2: Pointer): integer;
  2. //Asume that Tmyobject has a property Val which is integer.
  3. var o1 : TMyObject absolute Item1;
  4.     o2 : TMyObject absolute Item2;
  5. begin
  6.   Result := o1.Val - o2.Val;
  7. end;
  8.  

I know that _in general_ absolute could open a can of worms but in this context, where you are guaranteed that the variables and the params are sharing the same mem block, what would be the drawback to use absolute? It strikes me as a more elegant way than having to assign and typecast the params.

If you're sure that you're really only passing in descendants of TMyObject then in my opinion that is fine (maybe make sure that the function is only part of the implementation-section so that nobody abuses it ;) ). We use such constructs for various iterator functions in the compiler as well.

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1071
Re: var absolute anyone?
« Reply #12 on: October 04, 2021, 09:08:46 am »
In this case? Even when you already know the parameters are of type TMyObject?
Yes because code is constantly evolving and assumptions that are true at the time of writing might not be in the future. And I always want to get as many warnings and errors as possible to verify if my assumptions are not valid anymore.
I want my compiler to verify as much as possible.

The compiler will not do any verification when you use typecasts. Try:
It will
  • warn when you typecast from a class type to an unrelated class type
  • perform verification when you compile with -CR
Especially point 2 is useful: you can compile a test version with -CR to verify that everything is correct, and a release version without it and get the same performance as with absolute.

Warfley

  • Hero Member
  • *****
  • Posts: 2066
Re: var absolute anyone?
« Reply #13 on: October 04, 2021, 02:16:52 pm »
The compiler will not do any verification when you use typecasts. Try:
Of course it does, not between Pointer and classes, but for other types:
Code: Pascal  [Select][+][-]
  1. var
  2.   p: Integer = 42;
  3.   sl:TStringList;
  4.   c: Integer;
  5. begin
  6.   sl:=TStringList(p);
  7.   c:=sl.Count;
  8.   WriteLn('c: ',c);
As I said, programs are constantly evolving. Most bugs are not introduced because someone made a mistake while programming a function, most bugs are introduced when rolling out updates that change the behavior of the code such that the assumptions in some parts of the code do not hold anymore (was the result of some research papers, but I couldn't find then on the fly right now).
Sure you can create such a function now and this is perfectly fine, but if in 2 years from now, you or maybe a completely different developer changes this function signature without changing the function body.
This doesn't even need to be in a single step, for example in one update someone might think that for documentation purposes it is probably better to use a custom type name rather than pointer:
Code: Pascal  [Select][+][-]
  1. type
  2.   TMyObjectReference = Pointer;
  3.  
  4. function SortByIndex(Item1, Item2: TMyObjectReference): integer;
  5. //Asume that Tmyobject has a property Val which is integer.
  6. var o1 : TMyObject absolute Item1;
  7.     o2 : TMyObject absolute Item2;
  8. begin
  9.   Result := o1.Val - o2.Val;
  10. end;

Then some time down the line one thinks, hey, I want to use a caching mechanism and builds the following. At this point in most of the code where TMyObjectReference is used, typecasts are used and the developer completely forgott (or is new to the project and doesn't know) about this one function that uses absolute, so they do this:
Code: Pascal  [Select][+][-]
  1. type
  2.   TMyObjectReference = type LongInt;
  3.  
  4. var
  5.   MyObjectCache: specialize TDictionary<TMyObjectReference, TMyObject>;
  6.  
  7. operator := (ARef: TMyObjectReference): TMyObject;
  8. begin
  9.   Result := MyObjectCache[ARef];
  10. end;
This works completely fine in the test cases, which happen to not cover SortByIndex, because some developer was lazy and didn't create a unit test, and is pushed to the master branch and deployed to the customers, for whom then the application starts crashing left and right.

Long story short, if you use absolute, you basically are freezing the type structure as the way it is. If someone new doesn't know about this restriction, or forgets about it, it can easiely result in bugs without any warnings by the compiler.

This can also be a problem without overloading the casting operator. Because if someone wants to change the type of parameter, the easiest way, rather then searching every occurance, is to simply change it and let the compiler figure out where you need to apply changes (this is usually the way I go about when switching up types). With absolute it doesn't generate a compiler error but silently fails and results in invalid data accesses
« Last Edit: October 04, 2021, 05:26:59 pm by Warfley »

 

TinyPortal © 2005-2018