Scope of anonymous methods - delphi

One nice thing about anonymous methods is that I can use variables that are local in the calling context. Is there any reason why this does not work for out-parameters and function results?
function ReturnTwoStrings (out Str1 : String) : String;
begin
ExecuteProcedure (procedure
begin
Str1 := 'First String';
Result := 'Second String';
end);
end;
Very artificial example of course, but I ran into some situations where this would have been useful.
When I try to compile this, the compiler complains that he "cannot capture symbols". Also, I got an internal error once when I tried to do this.
EDIT I just realized that it works for normal parameters like
... (List : TList)
Isn't that as problematic as the other cases? Who guarantees that the reference is still pointing to an alive object whenever the anonymous method is executed?

Var and out parameters and the Result variable cannot be captured because the safety of this operation cannot be statically verified. When the Result variable is of a managed type, such as a string or an interface, the storage is actually allocated by the caller and a reference to this storage is passed as an implicit parameter; in other words, the Result variable, depending on its type, is just like an out parameter.
The safety cannot be verified for the reason Jon mentioned. The closure created by an anonymous method can outlive the method activation where it was created, and can similarly outlive the activation of the method that called the method where it was created. Thus, any var or out parameters or Result variables captured could end up orphaned, and any writes to them from inside the closure in the future would corrupt the stack.
Of course, Delphi does not run in a managed environment, and it doesn't have the same safety restrictions as e.g. C#. The language could let you do what you want. However, it would result in hard to diagnose bugs in situations where it went wrong. The bad behaviour would manifest itself as local variables in a routine changing value with no visible proximate cause; it would be even worse if the method reference were called from another thread.
This would be fairly hard to debug. Even hardware memory breakpoints would be a relatively poor tool, as the stack is modified frequently. One would need to turn on the hardware memory breakpoints conditionally upon hitting another breakpoint (e.g. upon method entry). The Delphi debugger can do this, but I would hazard a guess that most people don't know about the technique.
Update: With respect to the additions to your question, the semantics of passing instance references by value is little different between methods that contain a closure (and capture the paramete0 and methods that don't contain a closure. Either method may retain a reference to the argument passed by value; methods not capturing the parameter may simply add the reference to a list, or store it in a private field.
The situation is different with parameters passed by reference because the expectations of the caller are different. A programmer doing this:
procedure GetSomeString(out s: string);
// ...
GetSomeString(s);
would be extremely surprised if GetSomeString were to keep a reference to the s variable passed in. On the other hand:
procedure AddObject(obj: TObject);
// ...
AddObject(TObject.Create);
It is not surprising that AddObject keeps a reference, since the very name implies that it's adding the parameter to some stateful store. Whether that stateful store is in the form of a closure or not is an implementation detail of the AddObject method.

The problem is that your Str1 variable is not "owned" by ReturnTwoStrings, so that your anonymous method cannot capture it.
The reason it cannot capture it, is that the compiler does not know the ultimate owner (somewhere in the call stack towards calling ReturnTwoStrings) so it cannot determine where to capture it from.
Edit: (Added after a comment of Smasher)
The core of anonymous methods is that they capture the variables (not their values).
Allen Bauer (CodeGear) explains a bit more about variable capturing in his blog.
There is a C# question about circumventing your problem as well.

The out parameter and return value are irrelevant after the function returns - how would you expect the anonymous method to behave if you captured it and executed it later? (In particular, if you use the anonymous method to create a delegate but never execute it, the out parameter and return value wouldn't be set by the time the function returned.)
Out parameters are particularly difficult - the variable that the out parameter aliases may not even exist by the time you later call the delegate. For example, suppose you were able to capture the out parameter and return the anonymous method, but the out parameter is a local variable in the calling function, and it's on the stack. If the calling method then returned after storing the delegate somewhere (or returning it) what would happen when the delegate was finally called? Where would it write to when the out parameter's value was set?

I'm putting this in a separate answer because your EDIT makes your question really different.
I'll probably extend this answer later as I'm in a bit of a hurry to get to a client.
Your edit indicates you need to rethink about value types, reference types and the effect of var, out, const and no parameter marking at all.
Let's do the value types thing first.
The values of value types live on the stack and have a copy-on-assignment behaviour.
(I'll try to include an example on that later).
When you have no parameter marking, the actual value passed to a method (procedure or function) will be copied to the local value of that parameter inside the method. So the method does not operate on the value passed to it, but on a copy.
When you have out, var or const, then no copy takes place: the method will refer to the actual value passed. For var, it will allow to to change that actual value, for const it will not allow that. For out, you won't be able to read the actual value, but still be able to write the actual value.
Values of reference types live on the heap, so for them it hardly matters if you have out, var, const or no parameter marking: when you change something, you change the value on the heap.
For reference types, you still get a copy when you have no parameter marking, but that is a copy of a reference that still points to the value on the heap.
This is where anonymous methods get complicated: they do a variable capture.
(Barry can probably explain this even better, but I'll give it a try)
In your edited case, the anonymous method will capture the local copy of the List. The anonymous method will work on that local copy, and from a compiler perspective everything is dandy.
However, the crux of your edit is the combination of 'it works for normal parameters' and 'who guarantees that the reference is still pointing to an alive object whenever the anonymous method is executed'.
That is always a problem with reference parameters, no matter if you use anonymous methods or not.
For instance this:
procedure TMyClass.AddObject(Value: TObject);
begin
FValue := Value;
end;
procedure TMyClass.DoSomething();
begin
ShowMessage(FValue.ToString());
end;
Who guarantees that when someone calls DoSomething, that the instance where FValue points to still exists?
The answer is that you must guarantee this yourself by not calling DoSomething when the instance to FValue has died.
The same holds for your edit: you should not call the anonymous method when the underlying instance has died.
This is one of the areas where reference counted or garbage collected solutions make life easier: there the instance will be kept alive until the last reference to it has gone away (which might cause instance to live longer than you originally anticipated!).
So, with your edit, your question actually changes from anonymous methods to the implications of using reference typed parameters and lifetime management in general.
Hopefully my answer helps you going in that area.
--jeroen

Related

Why does Assigned return true for uninitialized variables?

I read many posts on forum about pointers, Assigned function, Free function, FreeAndNil function, etc... I already know Free function don't remove the pointer reference to an object assigned and FreeAndNil does it... All posts I read treat this subject considering Create method already was executed, or in other words, considering an object already created.
My question is: Why Assigned function returns true for a uninitialized object variable ?
Follow an example:
procedure TForm1.FormCreate(Sender: TObject);
var
Qry: TADOQuery;
begin
if Assigned(Qry) then
ShowMessage('Assigned')
else
ShowMessage('Unassigned');
Qry := TADOQuery.Create(nil);
if Assigned(Qry) then
ShowMessage('Assigned')
else
ShowMessage('Unassigned');
end;
That example displays 'Assigned' twice!
Conclusion: Immediately after Qry has been declared and before its create method has been executed the pointer to Qry isn't NIL !
If I put Qry := nil; at the first line into procedure above everything works fine... it displays 'Unassigned' and 'Assigned'.
Why??
Is there any safe way to know if a class variable already has its create method executed?
Your variable is a local variable and so is not initialized. It could contain any value.
The documentation says:
On the Win32 platform, the contents of
a local variable are undefined until a value is assigned to
them.
Note that, as an implementation detail, some types are managed and even local variables of managed types are initialized. Examples of managed types include: strings, interfaces, dynamic arrays, anonymous types and variants.
You ask:
Is there any safe way to know if a class variable already has its create method executed?
If that variable is a local variable, the answer is no. The onus falls to you the programmer. In practice it is seldom an issue because good code has short procedures which makes it harder for you to slip up. And even if you do the compiler will invariably warn you.
Other types of variables like class fields and global variables are initialized.
Because when creating a pointer, it cames with whatever garbage value was in that memory position. If you want to write NIL in it, it takes some CPU cycles, and I think it's not automatically done by Delphi because you may want something faster. In your example, why assign NIL to a variable, if soon afterwards you're going to put another value in it?
From the documentation of the Assigned function (emphasis mine):
Use Assigned to determine whether the pointer or procedure referenced by P is nil. P must be a variable reference of a pointer or procedural type. Assigned(P) corresponds to the test P<> nil for a pointer variable, and #P <> nil for a procedural variable.
Assigned returns false if P is nil, true otherwise.
Note: Assigned can't detect a dangling pointer--that is, one that isn't nil but no longer points to valid data. For example, in the code example for Assigned, Assigned won't detect the fact that P isn't valid.
The Assigned function is effectively implemented as:
function Assigned(const P): Boolean;
begin
Result := Pointer(P) <> nil;
end;
So the function isn't really checking whether the value truly is assigned. Rather it's checking a side-effect of being assigned.
As a result the function is guaranteed to return True if it is assigned.
But behaviour is undefined if the value is uninitialised. Basically since an uninitialised value has a garbage value left over from previous operations, it might be nil, or if might not.
Another thing to note is that Assigned has no way to determine the validity of its value. E.g. The following call to Assigned returns True even though the underlying object is no longer valid.
var
LObject: TObject;
begin
LObject := TObject.Create;
LObject.Free;
if Assigned(LObject) then ShowMessage('Still assigned!?');
end;
EDIT: Addendum
In response to the second part of your question.
Is there any safe way to know if a class variable already has its create method executed?
There is no safe way to determine if an object instance has been created. (There's also no way to reliably confirm that it hasn't already been destroyed.)
However, there are conventions (and good practices) you can follow to help you on the way.
First note that you should only be "unsure" if something was created if it's a deliberate feature of that piece of code. E.g. If you intend an object to be "lazy initialised".
What I'm trying to say here is: Never check Assigned just because you're worried that there might be a bug that prevents it from being assigned.
Not only is this impossible to do reliably, but you overcomplicate your code... Which increases the chance of bugs.
Also if you find something is unexpectedly not Assigned, then what can you do about it? Ignoring it would simply be pointless. Also, it's no good saying: "Ok, then I'll create the object". Because then you're duplicating creation logic in multiple places.
Basically you should try to make every part of your program correct - not have your program try to double-check itself everywhere.
So now that we're (hopefully) agreed that you only check if something is created if you've deliberately chosen that being created is optional. You do this as follows:
At first opportunity, ensure the variable/field reference is initialised to nil. So then it's guranteed to be assigned a value which means the object is not created. (Yes, the naming is a bit warped.)
You can set the vairable/field reference to a new instance of an object or set it by copying another reference of an already existing object. (Note the existing refernce might also be nil, but that doesn't cause any problems.)
If you ever destroy the object (or even just want to stop using it from that reference), set your variable/field reference to nil again.
NOTE: Delphi already initialises the member fields of a new class. So those won't need special attention.

delphi: inaccessible value on var parameter

I have this example method below
procedure ReadData(var data:TDataSet)
begin
if Assigned(data) then
data.Free;
data:=TDataSet.Create(nil);
....
end;
.....
procedure SomethingProcedure()
var
dataSet:TDataset;
begin
ReadData(dataSet);
end;
if I debugged and I place breakpoint on Assigned checking, data.Free always executed, and I saw on watch list, data always inaccessible value
My point is SomethingProcedure is access for many other procedure, and I want data parameter if it assigned (already created TDataset object), free it first, but if not assigned (not created object), free command doesn't execute, but free statement always executed, either "data" object created or not
How I can check my object already created or not
You have some issues with your code example
You declare dataset but pass data in your Init procedure
The if statement doesn't have a then in your ReadData procedure
All in all, you can not have been debugging the example you've given so I'm going to make some assumptions here.
I believe your actual problem is coming from the fact that local, not finalized variables do not get initialized to zero/nil. The dataset variable in your Init procedure contains whatever garbage happens to be at the location the variable points to.
Which variables are initialized when in Delphi?
As you don't initialize the local variable dataset (something you should always do with local variables), Assigned will return true (all it does is check for nil) and free will get called.
Most of the time and if you are lucky, the call to free will throw an AV. Worst case, it will succeed and you will have a really hard time figuring out why something is going wrong.
Edit
I assume by your edit that you mean that ReadData is called in many other procedures?
If that's the case, there really is not a lot you can (or for that matter should) do to protect you from callers passing in garbage. What you should do is fix the callers.
Fix the root cause, not the symptoms
First of all, you do not have to check your data object for assignment. It is perfectly safe to call Free method when data is pointing to nil.
As for the reason why you can not see on what the data is pointing to: you probably need to turn off the optimization for your project. To do this go to: Project > Options > Delphi Compiler > Compiling (this may vary depending on your Delphi version) and switch Optimization to False.

What's the difference between "var" and "out" parameters?

What's the difference between parameters declared with var and those declared with out? How does the compiler treat them differently (e.g., by generating different code, or by changing which diagnostics it issues)? Or do the different modifiers merely allow the programmer to document intended use of the parameters? What effect do the types of the parameters have on the matter?
A var parameter will be passed by reference, and that's it.
An out parameter is also passed by reference, but it's assumed that the input value is irrelevant. For managed types, (strings, Interfaces, etc,) the compiler will enforce this, by clearing the variable before the routine begins, equivalent to writing param := nil. For unmanaged types, the compiler implements out identically to var.
Note that the clearing of a managed parameter is performed at the call-site and so the code generated for the function does not vary with out or var parameters.
There is not much difference, for the compiler that is. See Mason's answer for that.
Semantically, there is a big difference:
var tells the programmer that the routine could work with its current value,
out tells the programmer that the routine will ignore/discard its current value.
Slightly late but just for the record, I came across a case where var or out made a big difference.
I was working on a SOAP web service which exported the following method:
function GetUser( out User :TUser ) :TResult;
which was getting imported into C# as the equivalent of
function GetUser( out Result :TResult) :TUser;
when I changed the out to a var it it imported correctly.
I'm guessing that the Delphi SOAP invoker treats the function result as an out parameter and that having two out parameters confuses the Delphi SOAP routines. I'm not sure if there is a workaround to allow you to use out parameters.
I read earlier that out parameter is set to default by called function, but today I realized that it is not completely true. Value of out parameter is discarded by called routine, but if that routine does not change its value, caller can still get it initial value, which was assigned before passing to called thread.
For example:
procedure JustNothing(out x : integer);
begin
// do nothing
end;
procedure TestOutVar;
var i : Integer;
begin
i := 100;
JustNothing(i); // after this call, i will still be 100
end;

Is it possible for a managed local variable to transparently "travel to" another local scope?

This question is related to my other one and I hope to get some ideas from it:
Is it possible for a local managed variable (record, interface, ...) to survice the local scope and "travel to" another one without using any explicit out/var parameters or result values?
Sorry if this sounds strange, but this would allow me to create a managed object inside a called method which will only be destroyed when the calling method ends, not the one it has been created in, while the whole process is entirely transparent to the caller (this is the main goal). The caller doesn't have to declare anything.
First hacky idea comes here:
(Mis-)Use the automagically created wrapper object for anonymous methods and attach data to it. My assumption is: this object is created in the callers local scope, lives during the callees local scope (so the callee can attach data to it), and lives on until the end; of the caller.
Is it possible to attach data to this wrapper object? Apart from hackyness: has it any chance of working?
Edit: Maybe an easier phrasing for the question could be: "How to pass a result value from a function without using any parameters or function result?"
Edit2: Writing some code makes me wonder whether I should let it go:
function TForm1.L<T>(Func: TFunc<T>):T;
var
Value: T;
begin
Result := Func;
// now attach something to the anon wrapper of Func
end;
function TForm1.O<T>(Value: T): T;
begin
Result := T;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
List: TList;
begin
for Item in L(O<TList>(List)) do
begin
end;
// List should be destroyed here
end;
I think I should.
Sorry if this sounds strange, but this would allow me to create a managed object inside a called method which will only be destroyed when the calling method ends, not the one it has been created in. This way I don't have to use out/var variables or return values (which is effectively my goal).
The managed local variable from the CALLED method need to, well, "travel" to the calling method. The only defined methodologies for something like that to happen is to use var, out or return the actual value. That's because all "managed" data types that can be "transported" are reference-counted. This includes Interfaces and strings.
Use the automagically created wrapper object for anonymous methods and attach data to it. My assumption is: this object is created in the callers local scope, lives during the callees local scope (so the callee can attach data to it), and lives on until the end; of the caller.
Delphi generates an actual TInterfacedObject descendents for anonymous methods. It'll generate ONE such descendent for each method/procedure that declares anonymous methods. The name of the generated object will be based on the name of the procedure where the anonymous method is declared. This objects has methods, one method for each anonymous methods used. It also has data fields: one field for each local variable used in the anonymous method, plus a reference to the object you're operating on.
See here for a detailed explanation: How and when are variables referenced in Delphi's anonymous methods captured?
The idea is, you can attach data fields to the anonymous method by simply declaring local variables in the same procedure that's declaring the anonymous method, and using them within that anonymous method. You'll then be able to get hold of that data, but it would be a hacky, difficult way: you'd need to cast the anonymous method to the implementing object (the anonymous method is actually an interface, so it can be done). Then you'd need to use RTTI to get hold of the fields holding your data. Doesn't seem very useful to me.

Bad reference to an object already freed

Is there a way to be sure we hold a useable reference to an object i.e. being sure it has not been already freed leaving that non nil reference dangling.
If you're using FastMM4 as your Memory Manager, you can check that the class is not TFreeObject.
Or, in a more standard case, use a routine that will verify that your object is what it says it is by checking the class VMT.
There have been such ValidateObj functions hannging around for some time (by Ray Lischner and Hallvard Vassbotn: http://hallvards.blogspot.com/2004/06/hack-6checking-for-valid-object.html)
Here's another:
function ValidateObj(Obj: TObject): Pointer;
// see { Virtual method table entries } in System.pas
begin
Result := Obj;
if Assigned(Result) then
try
if Pointer(PPointer(Obj)^) <> Pointer(Pointer(Cardinal(PPointer(Obj)^) + Cardinal(vmtSelfPtr))^) then
// object not valid anymore
Result := nil;
except
Result := nil;
end;
end;
Update: A bit of caution... The above function will ensure that the result is either nil or a valid non nil Object. It does not guarantee that the Obj is still what you think it is, in case where the Memory Manager has already reallocated that previously freed memory.
No. Unless you use something like reference counting or a garbage collector to make sure no object will be freeed before they have zero references.
Delphi can do reference counting for you if you use interfaces. Of course Delphi for .Net has a gargage collector.
As mentioned you could use the knowledege of Delphi or the memory manager internals to check for valid pointers or objects, but they are not the only ones that can give you pointers. So you can't cover all pointers even with those methods. And there also is a chance that your pointer happens to be valid again, but given to somebody else. So it is not the pointer you are looking for. Your design should not rely on them. Use a tool to detect any reference bugs you make.
Standard, no...
That's why VCL components can register themselves to be notified of the destruction of an object, so that they can remove the reference from there internal list of components or just reset their property.
So if you'd want to make sure you haven't got any invalid references their are two options:
Implement a destruction notification handler which every class can subscribe to.
Fix your code in a way that the references aren't spread around trough different object. You could for instance only provide the access to the reference via a property of another object. And instead of copying the reference to a private field you access the property of the other object.
As others have said, no definitive way, but if you manage the ownership well, then the FreeAndNil routine will ensure that your variable is nil if it doesn't point to anything.
It's usually not a good idea to check a reference is valid anyway. If a reference is not valid, your program will crash at the place where it is using the invalid reference. Otherwise the invalid reference might survive longer and debugging becomes harder.
Here are some references to why it's better to crash on an invalid reference. (They talk about pointers in Win32, but the ideas are still relevant):
IsBadXxxPtr should really be called CrashProgramRandomly
Should I check the parameters to my function?
Unfortunately there is no way to 100% guarantee that a pointer to anything is still valid, except by meticolously writing the correct code.
With the usage of interface references (instead of object references) it is possible to avoid these invalid pointer problems because there is no explicit call to Free in your code anymore.

Resources