I want to fill a TStringList inside a DLL. My approach seems to be wrong regarding memory management documentaion, but it works and doesn’t cause an error or AV.
Can someone tell me, if that code is OK? Not sure how I can fill a class in general in a DLL.
programm EXE
function MyClass_Create: IMyClass; stdcall; external ...
var
_myClass_DLL: IMyClass; //shared interface in exe and dll
procedure FillList;
var
list: TStringList;
begin
list := TStringList.Create(true); //memory allocated in EXE
try
_myClass_DLL.FillList(list); //memory allocated in DLL???
ShowMessage(list.Text);
finally
list.Free; //memory freed in EXE, frees also TObject created in DLL
end;
end;
DLL Code:
library DLL
TMyClass = class(TInterfacedObject, IMyClass)
public
procedure FillList(aList: TStringList);
end;
procedure TMyClass.FillList(aList: TStringList);
begin
aList.AddObject('Text1', TObject.Create); //memory allocation in DLL?
aList.AddObject('Text2', TObject.Create); //memory allocation in DLL?
end;
I don’t use BORLNDMM.DLL or any other ShareMem unit.
Edit:
I expanded the aList.Add() call to aList.AddObject(). It also doesn’t crash, altough the TObject is created in DLL and freed in EXE.
Answer:
Regarding the comments in the accepted answer below, that code is correct, since exe and dll are compiled with the same delphi version and only virtual methodes are invoked.
Conclusion:
As long as virtual methods or interfaces are used, there is no problem with memory management. That means, it doesn’t matter where the object is created or freed.
If you want to pass classes across module boundaries then you need to link to the RTL/VCL with runtime packages. That’s the only way to make sure that the
TStringListclass in your DLL is the exact same one as in your EXE. That is the fundamental problem with your current approach. On the other hand, if you are already linking to the RTL with runtime packages, then you are fine.If you don’t want to use runtime packages then you need to redesign your interface completely. You would need to stop passing classes across the module boundary. You can use interfaces, but not classes. And you would need to take control of the memory allocation to ensure that memory is always deallocated in the module that allocated it. Or start using
ShareMem.