SIGSEGV when using interfaces - interface

Please take a look at the following Free Pascal program.
type
IMyInterface = interface
end;
TMyClass = class(TInterfacedObject, IMyInterface)
end;
var
MyInstance: TMyClass;
procedure DoSomething(MyParameter: IMyInterface);
begin
end;
begin
MyInstance := TMyClass.Create;
DoSomething(MyInstance);
MyInstance.Free;
end.
The program crashes during the access to the destructor with a SIGSEGV when started from within the IDE (compiled with debug information). Why? It works when I use TInterfacedObject, TObject, or TMyClass as parameter type. It even works when I use the const keyword for said parameter. Can anyone explain this behavior? With a quick sideways glance to Java I would expect this to work.
Compiled with FreePascalCompiler 2.6.4, executed under Windows 7.

I cannot speak for FPC, but with Delphi it is a bad idea to mix interfaces and objects. In this case you have two solutions:
declare MyInstance as IMyInterface and remove the call to Free.
inherit TMyClass from TInterfacedPersistent.
To clarify what is actually happening: Creating the TMyClass instance and assigning it to MyInstance will keep the reference count to 0. When you pass it to DoSomething a cast to IMyInterface takes place and the reference counter increases. When DoSomething ends the reference counter decreases to 0 and the instance is freed. The following call to Free will free an already freed instance.

DoSomething expect a IMyInterface
when you pass MyInstance , it's make a counter control, so when the method DoSomething finish, MyInstance has a counter decrement.
the TMyClass is a TInterfacedObject, so when the counter = 0, then Object will be freed, so you don't need to call MyInstance.Free;
you can do:
DoSomething(TMyClass.Create);

Your Object uses Reference Counting, to free it you must decrement the reference count. An alternative is to use what's called CORBA interfaces.
In FPC object pascal mode a CORBA interface is a pure interface which does not derivates from IUnknown (in opposite to COM interfaces). If you add the compiler directive:
{$INTERFACES CORBA}
then you'll be able to use the .Free method, just like with any other TObject instance. Note that the name can be confusing since CORBA is a full cross-language specification (IDL), but here corba just means "not COM".
online reference:
http://www.freepascal.org/docs-html/ref/refse44.html#x98-1080007.6

Related

Why is this code working and how is Delphi instantiating a class in this case?

I'm doing the Delphi track at exercism, and following how Delphi generates code for a form, answered one of the basic questions like this:
unit uLeap;
interface
type
TSYear = class
public
{ public declarations here }
function isLeap(y: integer): boolean;
end;
var
TYear: TSYear;
implementation
function TSYear.isLeap(y: integer): boolean;
begin
result := ((y mod 4) = 0) and (((y mod 400) = 0) or ((y mod 100) <> 0));
end;
end.
the code compiles without a single complaint, I can run it step by step, and the "isLeap" function is called from another unit several times this way:
procedure YearTest.year_divisible_by_4_not_divisible_by_100_leap_year;
begin
assert.IsTrue(TYear.IsLeap(1996), 'Expected ''true'', 1996 is a leap year.');
end;
...
I've never explicitly created the instance of the class, but it seems as if Delphi is doing it somewhere, maybe when declaring TYear? Is that a valid way?
Despite passing all the tests the code was rejected because it isn't done the conventional way. I'll surely end up doing it differently to have it accepted, but, besides the bad naming, why is this working? Would this code cause problems somewhere I can't see in this simple example?
I've never explicitly created the instance of the class, but it seems as if Delphi is doing it somewhere, maybe when declaring TYear?
No, Delphi is NOT automatically creating an instance of you. When you declare a variable of a class type, it is simply a pointer variable that can be made to point at a valid instance. But you must always create this instance yourself, and save the pointer in the variable:
SYear := TSYear.Create; // create a `TSYear` object and save its address in `SYear`
Is that a valid way?
No.
[W]hy is this working?
Because you are lucky: The isLeap function doesn't access any fields on the class instance.
Would this code cause problems somewhere I can't see in this simple example?
If the function had been using any fields in the class instance, you would have ended up with an AV if lucky and memory corruption if unlucky.
The solution is either to create an instance and use it:
SYear := TSYear.Create;
try
ShowMessage(BoolToStr(SYear.IsLeap(2000), True));
finally
SYear.Free;
end;
Or, since you clearly don't need any instance variables to determine if a year is a leap year or not, it is better to make this a class method:
type
TSYear = class
public
class function IsLeap(AYear: Integer): Boolean; static;
end;
This way, it can be called without any class instance: TSYear.IsLeap(2000). Notice that TSYear is the class (type) name, not a variable of this type.
Please see the documentation for a great conceptual introduction to all these concepts.

IO language: what is the difference between a message send, do and doMessage

Although there is a documentation available, I got more confused, rather then enlightened. Let's consider an example:
I have a myObject instance, which has myMethod method and I call it from the lobby:
myObject myMethod
In this method's body following is done:
myObject1 anotherMethod //1
msg := message(anotherMethod)
myObject2 do(msg) //2
myObject3 doMessage(msg) //3
So, could anyone explain me differences between 1 2 and 3?
Who is the actual caller for these cases? The locals object of the method, the method object or myObject? Is there a difference between sender and caller (I suppose there is one in case of doMessage, where sender is the locals object of the myMethod, but the "caller" is myObject3)
Alright, so in order:
The message anotherMethod is received by the instance named myObject. This is done in the calling context (probably the Lobby, unless wrapped inside another do()
do() introduces a new scope, and does nothing with the calling scope. That is to say, you can't reference anything in the calling scope inside a do() unless it happens to be in the Protos hierarchy or introduced inside the do(). do() also takes a message tree, and so what you're doing is effectively sending message(msg) to be evaluated inside the context of myObject which doesn't make much sense since msg first off can't be found due to the scope not being available, and even if it was, wouldn't make a lot of sense. Generally, you want to do something like: msg doInContext(myObject) if you find yourself desiring to write myObject do(msg).
Is functionally equal to #1 above. In fact, if you were to write a compiler for Io code down to messages, this is more or less what you'd get out of that compilation step of #1. They're equivalent in this short example.

Why is 'init' not assignable?

I just read that the init method can't be used as a value. Meaning:
var x = SomeClass.someClassFunction // ok
var y = SomeClass.init // error
Example found on Language reference
Why should it be like that? Is it a way to enforce language level that too dirty tricks come into place, because of some cohertion or maybe because it interferes with another feature?
Unlike Obj-C, where the init function can be called multiple times without problems, in Swift there actually is no method called init.
init is just a keyword meaning "the following is a constructor". The constructor is called always via MyClass() during the creation of a new instance. It's never called separately as a method myInstance.init(). You can't get a reference to the underlying function because it would be impossible to call it.
This is also connected with the fact that constructors cannot be inherited. Code
var y = SomeClass.init
would also break subtyping because the subtypes are not required to have the same initializers.
Why should it be like that?
init is a special member, not a regular method.
Beyond that, there's no reason that you'd ever need to store init in a variable. The only objects that could use that function in a valid way are instances of the class where that particular init is defined, and any such object will have already been initialized before you could possibly make the assignment.
Initializers don't have a return value. In order to assign it to something, it should be able to return something - and it doesn't.

Delphi: Memory leak when creating a TStringList inside a class

I have this pieces of code
TSql = class
private
FConnString: TStringList;
public
property ConnString: TStringList read FConnString write FConnString;
constructor Create;
destructor Destroy;
end;
var
Sql: TSql;
...
implementation
{$R *.dfm}
constructor TSql.Create;
begin
//inherited Create;
FConnString:=TStringList.Create;
end;
destructor TSql.Destroy;
begin
FConnString.Free;
//inherited Destroy;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Sql.Create;
Sql.ConnString.Add('something');
showmessage(Sql.ConnString.Text);
Sql.Destroy;
end;
Why when creating the FConnString is creating a memory leak, after a press the button?
..................................
..................................
..................................
..................................
There are two things I see. The first of which was already covered by the other comments and answer regarding the lack of "override" on the destructor.
The second issue is the property declaration itself. In general, you should never declare a property that references an object field in the "write" clause. The reason is that assigning to that property will "leak" the existing instance in that field. Use a method for the "write" clause of the property declaration:
property ConnString: TStringList read FConnString write SetConnString;
...
procedure TSql.SetConnString(Value: TStringList);
begin
FConnString.Assign(Value);
end;
Also notice that this method does not overwrite the FConnString field either. It merely copies the "value" or the "content" of the Value TStringList into the FConnString instance. In this manner the TSql instance is in complete and total control over the lifetime of that field. It is the responsibility of the code assigning that property to control the lifetime of the Value TStringlist.
EDIT The actual problem
The original code in the question was as follows:
procedure TForm1.Button1Click(Sender: TObject);
begin
Sql.Create;
Sql.ConnString.Add('something');
showmessage(Sql.ConnString.Text);
Sql.Destroy;
end;
The problem line was Sql.Create; which should have been Sql := TSql.Create;. The reason this causes a memory leak is as follows:
Sql.Create; is called from a nil reference.
This calls TStringList.Create; and attempts to assigned the result to FConnString.
Because Sql is a nil reference, this triggers an Access Violation.
The problem is there is no way to destroy the TStringList instance that was created.
Additional problems in original answer
Your destructor is virtual, you're not overriding.
You're not calling your inherited Destructor.
TSql = class
private
FConnString: TStringList;
public
property ConnString: TStringList read FConnString write FConnString;
constructor Create;
destructor Destroy; override; //Correction #1
end;
destructor TSql.Destroy;
begin
FConnString.Free;
inherited Destroy; //Correction #2
end;
EDIT
A few general tips:
I applaud you for using composition (making FConnString a member instead of inheriting from TStringList). However, by exposing it publicly, you would lose many of the benefits. Specifically you would be exposed to Law of Demeter violations. I'm not saying never do it. But be aware that you can create a maintenance problem down the line if a large amount of client code accesses ConnString directly.
Declaring FConnString: TStringList; violates the principle of Program to an interface, not an implementation. TStringList is a specific implementation of TStrings and this declaration prevents use of other subclasses of TStrings. This is more of a problem combined with #1: if in a few years time you find and want to switch to a different/better subclass implementation of TStrings client code that is binding to TStringList now creates much more work and risk. Basically the preferred aproach can be summed up as:
Declare the variable as the abtract base type.
Create the instance as the specifically chosen implementation subclass.
Let polymorphism ensure subclass behaviour is applied correctly in overridden methods.
Again this is a general guideline. If you specifically need access to properties/methods that were added at the TStringList level of the hierarchy, then you have to bind to that class. But if you don't need it, don't do it.
You forgot to declare Destroy() with the override specifier, so TSql.Destroy is not actually being called when the object is destroyed.
destructor Destroy; override;
The object is not created correctly. It must be:
Sql:=TSql.Create;
From here is coming the memory leak.

How to declare type for a class method in Delphi?

How to declare type for a class procedure, for example
type
TTest = class
procedure Proc1;
class procedure Proc2;
class procedure Proc3; static;
end;
TProc1 = procedure of object;
TProc2 = ???;
TProc3 = ???;
TProc2 = procedure of object;
A class method still has a Self pointer. It's the class rather than the instance.
An interesting consequence of this is that it provides a way to implement event handlers without having to instantiate an object. For instance, you could use a class method of a class that that is never instantiated as a way to provide event handlers for the global Application object.
TProc3 = procedure;
A static class method has no Self pointer. It is assignment compatible with a plain procedural type.
Static class methods can be used as an alternative to globally scoped procedures. This does allow you to put such methods in a namespace, that of the class, and so avoid polluting the global namespace.
Take care when implementing static class methods that you do not call virtual class methods. Such calls are bound statically at compile time because the lack of a Self pointer means that dynamic polymorphic binding at runtime is not possible. Rather disappointingly the compiler fails to warn of this and so you do need to keep your wits about you.