InstanceClass.NewInstance vs InstanceClass.Create - delphi

what different between InstanceClass.NewInstance+Instance.Create and InstanceClass.Create;
Method1:
Instance := TComponent(InstanceClass.NewInstance);
Instance.Create(Self);
Method2:
Instance := InstanceClass.Create(Self);
Which is better?

I would always use InstanceClass.Create if it is appropriate – and invariably it is.
There are plenty of reasons. A very good one is that the single line version is more concise. Another is that the single line version is the standard, commonly used approach.
Yet another reason is the handling of exceptions in the constructor which your method 1 does not manage correctly. In case of an exception, the new instance will be destroyed, but the instance variable has still been assigned to. That's an important difference from method 2 and goes against all the lifetime management conventions of Delphi.
You mention TApplication.CreateForm. Let's take a look at it:
Instance := TComponent(InstanceClass.NewInstance);
TComponent(Reference) := Instance;
try
Instance.Create(Self);
except
TComponent(Reference) := nil;
raise;
end;
Remember that Reference is the form variable that you pass as a var parameter. The point about this is this code assigns that form variable before calling the constructor. Normally that assignment is only made after the constructor completes.
Presumably this is so that code which references the form variable (often a global variable) can work even if it is invoked from inside that form's constructor. This is a very special case and is overwhelmingly the exception rather than the rule. Don't let this special case drive your mainstream coding style.

(I added this answer, because IMHO others where not complete)
Method 2 is the correct one.
Method 1 if never to be called, since there is an hidden parameter to the constructor call, which may fail proper iniatialize: in fact, NewInstance is a per-class pseudo virtual method!
In fact, there is an hidden boolean parameter at constructor call (register EDX, since EAX=class). As stated by official documentation:
Constructors and destructors use the same calling conventions as other
methods, except that an additional Boolean flag parameter is passed to
indicate the context of the constructor or destructor call.
A value of False in the flag parameter of a constructor call indicates that the constructor was invoked through an instance object
or using the inherited keyword. In this case, the constructor behaves
like an ordinary method. A value of True in the flag parameter of a
constructor call indicates that the constructor was invoked through a
class reference. In this case, the constructor creates an instance of
the class given by Self, and returns a reference to the newly created
object in EAX.
In particular, when called that way, the class won't call the _ClassCreate function. It may fail to initialize the class, if the class is not to be created with the default NewInstance function. In fact, this function is inserted into the class VMT: in some rare cases, it may be overloaded (e.g. to provide another memory allocation pattern - may be a garbage collector or some speed-optimized allocator). So calling directly InstanceClass.NewInstance can be buggy, in some border cases.
function _ClassCreate(AClass: TClass; Alloc: Boolean): TObject;
asm
...
TEST DL,DL
JL ##noAlloc
CALL dword ptr [EAX].vmtNewInstance
##noAlloc:
...
Therefore, calling InstanceClass.NewInstance directly is only to be done on purpose, only if you want to cancel two overridden vmtNewInstance / vmtFreeInstance (and in this case, you may have to also NOT call .Free / .Destroy, but you own memory free function). So: never call NewInstance, but the constructor, as designed and documented by Embarcadero (and FreePascal team by the way), unless you need to make some internal low-level tweak.
NEVER use method 1 to create an object! It may work 99.9 % of the time, but may fail some cases, or with a compiler/RTL enhancement in the future (like a garbage collector). Even if the VCL sometimes uses NewInstance, you should not use it - I would rather prefer this method to be made protected.

Second is better because it is a standard method to create a class instance, while procedural form should be used within constructor to call inherited constructor.

Related

Is there a way to dynamically type cast by class information parameter in Delphi?

I am having some difficulty understanding typecasting when using a class that is a passed parameter. I tried searching for this but couldn't find other answers.
I am working with some legacy Delphi code, using Delphi 2006, which doesn't support Generics (introduced in Delphi 2009).
The code is using TLists to store pointers to instantiated classes of particular types. When clearing the list, they use this:
procedure ClearList(AList: TList);
var i: Integer;
begin
for i := 0 to AList.Count - 1 do
TObject(AList[i]).Free;
AList.Clear;
end;
And it is called like this:
ClearList(FExtraVisitTypes);
ClearList(FDiagnoses);
ClearList(FProcedures);
ClearList(FImmunizations);
ClearList(FSkinTests);
ClearList(FPatientEds);
ClearList(FHealthFactors);
ClearList(FExams);
My understanding of this may be off, but I am concerned that if the pointed-to objects are freed as TObject, that the destructor of the descendant object won't be called, potentially leading to a memory leak. (My polymorphisim kung-fu is a bit rusty, which may be causing my confusion.)
So I tried to change the clear function as below:
procedure ClearList(AList: TList; ItemClass: TPCEItemClass); //mod to add ItemClass
var i: Integer;
begin
for i := 0 to AList.Count - 1 do begin
(AList[i] as ItemClass).Free;
end;
AList.Clear;
end;
TPCEItemClass is defined like this:
TPCEItemClass = class of TPCEItem;
I then changed the clear calls like this:
ClearList(FExtraVisitTypes, TPCEProc);
ClearList(FDiagnoses, TPCEDiag);
ClearList(FProcedures, TPCEProc);
ClearList(FImmunizations, TPCEImm);
ClearList(FSkinTests, TPCESkin);
ClearList(FPatientEds, TPCEPat);
ClearList(FHealthFactors, TPCEHealth);
ClearList(FExams, TPCEExams);
But the compiler won't allow this and gives this error:
[Pascal Error] uPCE.pas(1730): E2015 Operator not applicable to this operand type
For this erroneous line:
(AList[i] as ItemClass).Free;
Questions:
Does the original way of coding, where the item is freed by simply calling the great-great-great (etc) ancestor Free method end up effecting the descendant's destructor method? As I write this, I'm now thinking that it actually does. But I don't know why. So any answers to help me keep this in my head would be great.
Why does my method of trying to typecast via the parameter which is of type class not work? Is this just not allowed? Or is my syntax wrong? Is there another way to do this?
Am I going about this all wrong? Is there a better way?
Thanks
I am concerned that if the pointed-to objects are freed as TObject, that the destructor of the descendant object won't be called, potentially leading to a memory leak.
That is not the case for classes that are properly implemented.
All classes derive from TObject. TObject.Free() calls the TObject.Destroy() destructor, which is virtual. Any descendant that requires destruction logic must override that destructor (if it doesn't, it has a flaw that needs fixing).
So, in properly written code, the original code will work perfectly fine as shown. Calling Free() on any valid and correctly implemented object will invoke its most-derived destructor.
Now, that being said, there have been plenty of cases over the years of people forgetting to override the destructor when their classes require it, thus causing the kinds of memory leaks you are worried about. So, make sure you pay attention to what your classes are doing, and you will be fine.
So I tried to change the clear function as below ... But the compiler won't allow this and gives this error
Correct, because you can't perform a type-cast on an object using a variable to a metaclass type, like you are trying to do. Type-casts require the target type to be specified at compile-time, but metaclass variables are not assigned until runtime.
Does the original way of coding, where the item is freed by simply calling the great-great-great (etc) ancestor Free method end up effecting the descendant's destructor method?
The original code will work just fine 99% of the time, yes. Most Delphi coders are good about override'ing the destructor when it is appropriate. But that other 1% is only when you are dealing with classes that are not implemented correctly, in which case it is their author's responsibility to fix them, not your responsibility to fix the code that is calling Free() on them.
As I write this, I'm now thinking that it actually does. But I don't know why.
Polymorphic dispatch of the virtual destructor, just like when calling any other virtual method.
Why does my method of trying to typecast via the parameter which is of type class not work? Is this just not allowed?
Correct. It is illegal.
Is there another way to do this?
No (well, yes, but it involves walking an object's class structure's manually at runtime, but that requires a deep understanding of how the compiler lays out objects in memory, so I'm not going to get into that here).

Class doesn't work when defined as a global variable in delphi

I created a simple class to explain my problem:
ttest =class
private
val:boolean;
published
function get:boolean;
end;
...
function ttest.get: boolean;
begin
val:=not val;
result:=val;
end;
Now if I declare a local ttest variable and call my_var.get; then everything works, but if I declare it as a global variable then it can't access the val field anymore, it shows an error message which says "Access violation...".
I read some articles about classes in Delphi but still can't find my mistake.
You've neglected to instantiate the class.
Global class-reference variables are initialized to nil, whereas local variables are not initialized at all. The local variable has a value determined by whatever happened to be on the stack at the time you called your function, and your program is interpreting that value as though it were a TTest reference even though it's really not. Your program then reads the value at that memory address to get the value that would represent the val field.
The only reason your code appears to work with a non-global variable is luck. Whether it's good luck or bad is another matter. (Good luck, since your code appeared to work, and working code is always nice. Bad luck, since you'd have been alerted to your mistake earlier if your code had crashed.)
Instantiate a class before you use references to it.
x := TTest.Create;
Now you can access fields, methods, and properties of the object via the x variable.
You should have gotten a compiler warning when you attempted to use a local variable without assigning a value to it first. Although they're just warnings, and your program will still run, never ignore a warning or even a hint. When the compiler bothers to complain about something, it's usually right.
In Delphi object variables are always pointers. Before you can use the variable you need to initialize it with a reference to an object. The most common way to do that is to create a new object of the particular class.
procedure Foo;
var
Obj: TObject;
begin
Obj := TObject.Create;
try
// Do stuff with Obj
finally
Obj.Free;
end;
end;
In this case Obj starts out as an uninitialized pointer (it will point to random memory). It is only after we assign the newly created TObject that Obj is a valid object reference.
In Delphi there is no automatic garbage collection for objects, so you always need to call free on them when you are done using them. If you declare a global or local object variable, you can initialize it the special initialization section of the unit and free the object in the finalization section.
unit myunit;
interface
var
Obj: TObject;
implementation
initialization
Obj := TObject.Create;
finalization
Obj.Free;
end.
Variables declared in the interface section are globally visible, variables declared in the implementation section are only visible inside the unit. It should be noted that declaring a global object variable means that any unit can overwrite the variable with a reference to a new object without freeing the existing object first. This would cause a memory leak as again there is no automatic garbage collection.
A delphi class is basically just a description, not the object itself. You describe the properties and methods the final object should have. And the missing piece of the puzzle is that you havent really told Delphi to create an object from your class.
This is done by calling the constructor:
mMyInstance:=TTest.Create;
The constructor takes the class description and builds an object instance for you in memory. It returns a pointer to the object which you must store in a variable (myInstance in the above example) of the same type.
Reading your question, I suspect you want to create an object that is "always there", a bit like the printer object. This is easy to do, but just like the printer object - you must include that unit before you can access the object. I think Anders E. Andersen above has shown how most people would initialize an object from a unit centric point of view.
If you want the object to be reachable from another unit, say your mainform or any other unit, first add "myunit" to the uses list. Then to make it visible you add a function, like this:
function test:ttest;
Begin
result:=obj;
end;
And remember to add "function test:TTest" to the interface section of the unit. Then you can use the object from another unit as such:
myUnit.test.get;
But be warned! This is pretty old school programming, and you run the risk of your unit being released (which calls finalization and thus destroys your object) before the other units are done with it. Thus you risk calling a function in an object which no longer exists in memory - causing a spectacular access violation when your program closes.
If you want to learn Delphi properly, head over to Delphi Basics and read up on the basic principles. It takes a while to learn a new language but you will soon get the hang of it.
Good luck!

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.

Delphi7, passing object's interface - causes Invalid Pointer Operation when freeing the object

I have a class that implements an interface, which is made available for plugins.
The declaration of class is quite simple. There is only one instance of this class for an entire application. When the function that returns the interface is called, it calls _AddRef on the retrieved interface before passing it back as result. Unfortunately it works until I try to free the object (see "finalization" section) - it reports Invalid Pointer Operation. If I comment it out, it works fine (however FastMM reports memory leaks, so the object is not being freed).
Here is the part of the code in the function that returns the interface (in fact it is an overridden QueryInterface of my "ServicesManager" class).
if ConfigManager.GetInterface(IID, obj) then
begin
ISDK_ConfigManager(obj)._AddRef;
result:= 0;
end
and the code of ConfigManager class ...
type
TConfigManager = class(TInterfacedObject, ISDK_ConfigManager)
private
...
end;
var
ConfigManager: TConfigManager;
implementation
...
initialization
ConfigManager:= TConfigManager.Create();
finalization
if ConfigManager <> nil then
FreeAndNil(ConfigManager); //if I comment it out, it leaks the memory but no Invalid Ptr. Op. raises
What am I doing wrong?
I need to pass a reference to exactly this instance of ConfigManager.
The number one piece of advice you'll hear when dealing with interfaces is to never mix interface references with object references. What this means is that once you start referring to an object via an interface reference, you cease to refer to it via an object reference. Ever.
The reason is that the first time you assign an interface variable, the reference count of the object will become 1. When that variable goes out of scope or gets assigned a new value, the reference count becomes zero, and the object frees itself. This is all without any modification of the original object-reference variable, so when you later try to use that variable, it's not a null pointer, but the object it referred to is gone — it's a dangling reference. When you try to free something that doesn't exist, you get an invalid-pointer-operation exception.
Declare your ConfigManager variable as an interface. Don't free it yourself. Once you do that, you can move the entire declaration of TConfigManager into the implementation section because no code outside that unit will ever refer to it.
Also, there's rarely any reason to provide your own implementation of QueryInterface. (You said you overrode it, but that's impossible since it's not virtual.) The one provided by TInterfacedObject should be sufficient. The one you're providing is actually causing a memory leak because you're incrementing the reference count when you shouldn't be. GetInterface already calls _AddRef (by performing an interface assignment), so you're returning objects with inflated reference counts.
You said this is a plugin system? Are you loading your plugins as BPLs? I ran into that problem last week, actually. You can't rely on finalization to clear your interface references. You need to make sure to clear them before you unload the plugin, or its memory space becomes invalid.
Edit: By "clearing interface references" I mean calling _Release on them, either by manually setting it to nil or by letting the references go out of scope. If your interface manager holds interface references to the plugins, they'll get cleared when the interface manager gets destroyed.
I totally agree with Rob.
What most likely helps is rewriting your initialization code like below.
Now ConfigManager is of type ISDK_ConfigManager, and by assigning nil to it, the reference count will decrement.
When the reference count becomes zero, it will automatically become freed.
type
TConfigManager = class(TInterfacedObject, ISDK_ConfigManager)
private
...
end;
var
ConfigManager: ISDK_ConfigManager;
implementation
...
initialization
ConfigManager:= TConfigManager.Create();
finalization
ConfigManager := nil;
end;
--jeroen
does TConfigManager class has any method declared as "published"?

Scope of anonymous methods

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

Resources