Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DLLs - FreeLibrary problem 1

Status
Not open for further replies.

KempCGDR

Programmer
Jan 10, 2003
445
GB
Hi, I have this piece of code in the onJoin event of an Indy IRC Client:

Code:
procedure TfrmMain.ircJoin(Sender: TObject; AUser: TIdIRCUser; AChannel: TIdIRCChannel);
type
   TonJoin = function(AUser: TIdIRCUser; AChannel: TIdIRCChannel):String;
var
   Temp:PChar;
   LibraryID:THandle;
   proc:pointer;
   command:String;
begin
   displayEvent(AUser.Nick, 'has joined the chat');
   listUsers;

   Temp := PChar(ExePath + dll);
   LibraryID := LoadLibrary(Temp);
   If LibraryID <> null then
   begin
      proc := GetProcAddress(LibraryID, 'onJoin');
      if proc <> nil then
      begin
         command := TonJoin(proc)(AUser, AChannel);
         displayChat(irc.Nick, command);
         irc.Say(currChannel, command);
      end;
      freeLibrary(LibraryID);
   end;
end;

It basically allows me to do basic scripting via a DLL. It all works fine except that after this code has ran once, the client appears to ignore any new incoming messages and disconnecting results in a socket error. After a lot of testing and swearing I managed to narrow it down to the FreeLibrary call, if I comment that out then it works perfectly and nothing dies. Is there anything blatently wrong with that code? I can't see it for the life of me.
 
are you using threads in the DLL ?

--------------------------------------
What You See Is What You Get
 
the dll function is the most simple one I could write for testing purposes:

Code:
function onJoin(AUser: TIdIRCUser; AChannel: TIdIRCChannel):String;
begin
   onJoin := 'Hi ' + AUser.Nick;
end;


I don't see that there could be anything bad going on there.
 
very bad things!!!, you are passing strings from DLL to app, this requires that you use the Sharemem Unit from borland. that's why you get the AV on freeing the DLL.
you got 2 options here :

1) use ShareMem (then you must include borlands borlndmm.dll) or a third party memory manager (I use FastShareMem (google it), no DLL required, just use the unit in both the app and the DLL)

or
2) avoid using strings between app and DLL and use Pchar.

and you got a third option but I don't recommend this one :

use shortstrings, these don't require a sharemem unit.

hope this helps,

Daddy

--------------------------------------
What You See Is What You Get
 
*slaps forehead*

Ok, I'm an idiot. I knew about that as well and I've done this before the right way. How could I forget something so basic? Especially when there's a big warning in the comment block that it gives you.

As a sidenote, it also failed all the time when I was using a TStringList, I assume that was a related reason. Are there any objects like a TStringList that store PChars, or am I going to have to make one myself? I'll move over to PChars for now though.

And one last thing, lol. Say you have this:

Code:
function foo:WhateverObject
var
   bar : WhateverObject;
begin
   bar := WhateverObject.Create;
   {various operations on bar}
   foo := bar;
end;

Is bar freed automatically when the function finishes executing or will this create a memory leak? Obviously if you free bar yourself at the end then foo now points to nothing (well, nothing that's valid) and you get nothing back from the function.
 
that is totally up to you. if you free foo in the function where you called it, everything's ok, don't freeing foo will indeed create memory leaks. Offcourse there are some objects that can do the dirty work for you :

Code:
// dll

function foo:WhateverObject
var
   bar : WhateverObject;
begin
   Result:=nil
   try
   bar := WhateverObject.Create;
   {various operations on bar}
   Result := bar;
   except
    // if we have an exception foo will be nil
   end;
end;


//app

uses contnrs;
...
var allmyobjects : TObjectList;
...
constructor TApp.init;
begin
 // create a Tobjectlist that owns the objects
 // this means that the object will be freed upon deletion from the list 
 allmyobjects:=TObjectList.Create(True);
end;

destructor TApp.cleanup;
begin
 allmyobjects.Clear; // this will free all objects in the list
 // this is not really needed since clear is called upon TObjeclist.Destroy
 // but is handy to know at what point your objects are freed
end;

...
procedure TApp.callingfoo;


var fooObject : TFooObject;
begin
 fooObject:=foo;
 if foo <> nil then
  alllmyObjects.add(fooObject); // add to list for auto destroy
 else
  //exception handling 
 ....
end;

cheers,

Daddy

--------------------------------------
What You See Is What You Get
 
Yeah, it occured to me last night (I do all my best thinking when I'm meant to be going sleep) that if you don't free bar then the object is still hanging around in memory, but the return from the function gives you a new pointer to that object that you can use to free it (as you've done in the example above).

Thanks a lot for all the help
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top