I would strongly discourage passing object instances between an executable and a regular DLL. Mainly for the exact reasons you are are encountering. What happens if the DLL is rebuilt and you've changed the object in some incompatible subtle way?
As Mason points out, packages are the preferred way to partition your application into modules.
3 And the object doesn't need to change itself. Correct me if I'm wrong, but compiler directives alone can alter the binary representation of the object. (If data alignment has no effect on objects, I'm pretty sure the "minimum enum size" switch will).
– Ken Bourassa Jul 17 '10 at 6:56 Yes, that among other things. Adding or even rearranging the order of virtual methods in the declaration. Changing method parameters (types, number, etc) or calling convention.
Then again, this still applies to packages, but at least the Windows loader should catch a lot of those things because the export signature of the methods will change. Also, the compiler will help to detect that the dependent modules will need to recompile. C++, OTOH, really leaves you twisting in the wind a lot more ;-) – Allen Bauer Jul 17 '10 at 19:11 Exactly.
Use Packages or don't share objects. – Warren P Jul 22 '10 at 14:20.
You can't share strings and objects between Delphi and a DLL if the DLL has its own memory manager. Since you're using Delphi 2010, you should have FastMM installed by default. Add "SimpleShareMem" as the first thing in the uses list for both the DLL and the EXE, and see if that doesn't fix the problem?
EDIT: In response to additional information from the poster: You're calling dic. Free after you unload the DLL. Even if you share memory managers, that's going to give you an access violation.
Here's why. Free calls TObject. Destroy, which is a virtual method.
The compiler generates code to look it up in the object's Virtual Method Table. But the VMT is stored in static memory that's specific to the module, not in shared memory allocated by the memory manager. You unloaded the DLL and pulled the rug out from underneath the VMT pointer in the object, and so when it tries to call a virtual method you get an access violation.
You can fix this by making sure to call Free before unloading the DLL. Or you can use runtime packages instead of a DLL, which gets around this problem by putting the VMT for the object in an external package that won't be unloaded before you're done with it.
Mason: Yes, this code will get an exception when 'Dic. Free' is execute. And, I have try your suggestion, add "ShareMem" or "SimpleShareMem" both in the uses list.
But, the problem can't be resolved. Thx! – user394386 Jul 17 '10 at 0:34 @neo2010: OK, that helps.
I'll edit my answer. – Mason Wheeler 6 Jul3 at 0:43 Think you,Mason. I got it, your advise is very helpful to me!
So, again, many, many thanks! :) – user394386 Jul 17 '10 at 0:53 I finally found what the real problem is! For..in keys loop will cause TDictionary create an instance for its data field FKeyCollection: function TDictionary.
GetKeys: TKeyCollection; begin if FKeyCollection = nil then FKeyCollection := TKeyCollection. Create(Self); Result := FKeyCollection; end; When the dll is unloaded, the memory FKeyCollection pointed is also freed, thus left a "dangling pointer". Destructor TDictionary.
Destroy; begin Clear; FKeyCollection. Free; FValueCollection. Free; inherited; end; – user394386 Jul 18 '10 at 13:00 @neo2010 - please listen to Allen and NEVER share any TObject-derived class between a DLL and the main EXE, unless you are using Runtime Packages.
Too many weird failures. – Warren P 6 Jul3 at 14:21.
I finally found what the real problem is! It seems like this: "For..in keys" loop will cause TDictionary create an instance for its data field FKeyCollection: function TDictionary. GetKeys: TKeyCollection; begin if FKeyCollection = nil then FKeyCollection := TKeyCollection.
Create(Self); Result := FKeyCollection; end; So when the dll is unloaded, the memory that FKeyCollection pointed is also freed, thus left a "dangling pointer". Destructor TDictionary. Destroy; begin Clear; FKeyCollection.
Free; //here will throw an exception FValueCollection. Free; inherited; end.
If you're still sharing a pointer to a TObject between the DLL and the main EXE, you're committing a Delphi "sin", and you will find more glitches in the future. Don't. – Warren P Jul 22 '10 at 14:22.
Thinks to you guys all. I have fix this problem by using COM. I even bulit an out-process automation server.It fits my program well.
Best regarts!
I would strongly discourage passing object instances between an executable and a regular DLL. Mainly for the exact reasons you are are encountering. What happens if the DLL is rebuilt and you've changed the object in some incompatible subtle way?
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.