Board index » delphi » DLL - Result is PChar - Causes Memory leak

DLL - Result is PChar - Causes Memory leak

Hi all,

I'm having a major problem:

I want to call a DLL from my Oracle Database using an SQL select. That part
works, so don't worry about that. This is the problem:

Oracle (8i) works with strings of the CHAR type (VARCHAR2 doesn't seem to
work), which are NULL terminated. The Delphi-version of this is PChar. The
problem is that I cannot free the memory of the Result variabele, because I
then loose my data. The DLL is hosted by an Oracle application called
ExtProc, so I cannot modify that either. I tried with other datatypes
(ShortString, WideString, String, ...), but they are not compatible with
Oracle.

Arguments of the type PChar that are passed to the function, are allocated
by ExtProc before calling the DLL, and (I guess) they are de-allocated
correctly.
The Result variable is allocated automatically when it's being used, and
ExtProc doesn't seem to care about it.

ExtProc remains active as long as the user is connected to the database, but
that doesn't mean the DLL remains loaded. I tried using a global variable
and allocate it once (by checking if it's allocated), but it seems to be
allocated on every function call. So the memory space remains used, but the
pointer disappears.

I ran a test and after only 15 hours of calling the function, i lost 5 Mb of
memory. This application should run on a server in a production environment.
So rebooting every couple of weeks is impossible.

A simple example:

function GetName(Employee: PChar; EmpInd: SmallInt; ResultInd: SmallInt):
PChar; cdecl;
var
LName: String;
begin
Result := #0;
LName := dbNameByEmpId(Employee); // function that retuns a string
Result := PChar(LName);
end;

Thanx in advance,

Stijn Van De Putte

 

Re:DLL - Result is PChar - Causes Memory leak


Rules:
1) A PChar is a pointer to an allocated memory block that contains some
text, usually nil terminated.
2) A Pointer must be allocated and deallocated by the same memory manager.

You have three pieces of code:
A) Your main application
B) Your DLL
C) The Oracle library (OCI)

If you're not using the borland shared memory manager (between A and B),
then you'll have to explicitly allocate and deallocate memory for the
strings.

The easy way to do all this is to pass PChar's between each of the modules
(like you're doing now), but use the string datatype and cast to PChars as
necessary.

Example:
{Inside B, exported}
function GetText: PChar;
var
    MyText: string;
begin
    MyText := GetTextFromDatabase;
    Result := PChar(MyText);
end;

{Inside A, imported function call}
procedure WorkWithDLLText;
var
    DLLText: string;
begin
    DLLText := DLLGetText; // Delphi automatically allocates and copies
return text into DLLText.
    ShowMessage(DLLText);
end;

The idea being that using a string datatype inside each piece (A, B) lets
Delphi handle the memory management for the string automatically, but when
passing data between pieces, cast to a PChar and let the following piece
handle the text.

Eric

Re:DLL - Result is PChar - Causes Memory leak


Hi there,

Sharemem must be the first unit declared in your DLL source to do this type
of string passing.

Enjoy...
Hannes Gouws

Quote
"Eric Hill" <e...@ijack.net> wrote in message news:3c59ad62$1_2@dnews...
> Rules:
> 1) A PChar is a pointer to an allocated memory block that contains some
> text, usually nil terminated.
> 2) A Pointer must be allocated and deallocated by the same memory manager.

> You have three pieces of code:
> A) Your main application
> B) Your DLL
> C) The Oracle library (OCI)

> If you're not using the borland shared memory manager (between A and B),
> then you'll have to explicitly allocate and deallocate memory for the
> strings.

> The easy way to do all this is to pass PChar's between each of the modules
> (like you're doing now), but use the string datatype and cast to PChars as
> necessary.

> Example:
> {Inside B, exported}
> function GetText: PChar;
> var
>     MyText: string;
> begin
>     MyText := GetTextFromDatabase;
>     Result := PChar(MyText);
> end;

> {Inside A, imported function call}
> procedure WorkWithDLLText;
> var
>     DLLText: string;
> begin
>     DLLText := DLLGetText; // Delphi automatically allocates and copies
> return text into DLLText.
>     ShowMessage(DLLText);
> end;

> The idea being that using a string datatype inside each piece (A, B) lets
> Delphi handle the memory management for the string automatically, but when
> passing data between pieces, cast to a PChar and let the following piece
> handle the text.

> Eric

Re:DLL - Result is PChar - Causes Memory leak


I'm not so sure about that, it seems that a PChar is being passed which
shouldn't require ShareMem.
I thought the point (at least one point) behind PChar was NOT having to use
ShareMem.
I think you have to explicitly free the memory allocated for the text
though, don't you?
Something seems a little strange there.

Rob

Quote
"Hannes Gouws" <Hann...@ComparexAfrica.co.za> wrote in message

news:3c63b682_2@dnews...
Quote
> Hi there,

> Sharemem must be the first unit declared in your DLL source to do this
type
> of string passing.

> Enjoy...
> Hannes Gouws

> > Example:
> > {Inside B, exported}
> > function GetText: PChar;
> > var
> >     MyText: string;
> > begin
> >     MyText := GetTextFromDatabase;
> >     Result := PChar(MyText);
> > end;

> > {Inside A, imported function call}
> > procedure WorkWithDLLText;
> > var
> >     DLLText: string;
> > begin
> >     DLLText := DLLGetText; // Delphi automatically allocates and copies
> > return text into DLLText.
> >     ShowMessage(DLLText);
> > end;

Re:DLL - Result is PChar - Causes Memory leak


I'm not so sure about that, it seems that a PChar is being passed which
shouldn't require ShareMem.
I think you have to explicitly free the memory allocated for the text
though, don't you?
Something seems a little strange there.

Rob

Quote
> > Example:
> > {Inside B, exported}
> > function GetText: PChar;
> > var
> >     MyText: string;
> > begin
> >     MyText := GetTextFromDatabase;
> >     Result := PChar(MyText);
> > end;

> > {Inside A, imported function call}
> > procedure WorkWithDLLText;
> > var
> >     DLLText: string;
> > begin
> >     DLLText := DLLGetText; // Delphi automatically allocates and copies
> > return text into DLLText.
> >     ShowMessage(DLLText);
> > end;

Re:DLL - Result is PChar - Causes Memory leak


Sorry about double-posting.
I can be such an idiot.

Re:DLL - Result is PChar - Causes Memory leak


Quote
"Robby Tanner" <rtan...@cls.usask.ca> wrote in message

news:3c640375_2@dnews...

Quote
> I'm not so sure about that, it seems that a PChar is being passed which
> shouldn't require ShareMem.
> I thought the point (at least one point) behind PChar was NOT having to
use
> ShareMem.

That depends on how you are setting that pchar. If you are allocating memory
for it (e.g. with GetMem) then it should be fine, if you are casting a
Delphi string to a pchar then you are simply passing the address of the
Delphi string, and that is a problem.

--
Wayne Niddery (Logic Fundamentals, Inc.)
RADBooks: http://www.logicfundamentals.com/RADBooks/delphibooks.html
In a tornado, even turkeys can fly. - unknown

Other Threads