Discussion:
Leaking Memory using COM and WideString
(too old to reply)
Kathleen Beaumont
2003-10-17 13:44:51 UTC
Permalink
I'm reposting this question because we never got it answered in our
original post.

We have a COM object that allocates memory for a BSTR. The client
accepts the return value from the COM object into a WideString variable.

We discovered (using AQTime 3) that this was causing a memory leak, and
we now understand why. Our solution is to change the code in the COM
object and in the client so that the client passes in a WideString (or
PCHAR) argument by reference, the COM object fills it, and thus the
memory management all takes place in the client.

THE QUESTION IS:

Is there any way for Delphi to free the memory allocated by a COM object?

We could manage it with a C++ Builder client (using a BSTR to accept the
return value from the COM, and invoking ::SysFreeString to deallocate
the memory). But if such an arrangement is possible using Delphi, we
couldn't make it happen.

Just want to know.

Thanks,
Kathleen
Danny Heijl
2003-10-21 09:54:50 UTC
Permalink
Post by Kathleen Beaumont
Is there any way for Delphi to free the memory allocated by a COM object?
SysFreeString is defined in the "ActiveX" unit and can be used to free an
OleString/BSTR (perhaps after you have copied the BSTR with OleStrToString).

Danny
---
Kathleen Beaumont
2003-10-21 13:54:01 UTC
Permalink
Danny,

Thanks for responding. As I mentioned in the post to which you
responded, we tried many combinations of variable declarations and calls
to SysFreeString in a test Delphi app.

I'm not a Delphi programmer-- I work with BCB-- but I would like to find
an example for my project manager (who codes both in Delphi and BCB) so
that we can run this issue to ground once and for all.

So, could you please post an example of the declaration and handling of
SysFreeString in Delphi so that we can try it out in our environment?

Thanks so much for your help.

Kathleen
Post by Danny Heijl
Post by Kathleen Beaumont
Is there any way for Delphi to free the memory allocated by a COM object?
SysFreeString is defined in the "ActiveX" unit and can be used to free an
OleString/BSTR (perhaps after you have copied the BSTR with OleStrToString).
Danny
---
Danny Heijl
2003-10-21 15:43:37 UTC
Permalink
Post by Kathleen Beaumont
So, could you please post an example of the declaration and handling of
SysFreeString in Delphi so that we can try it out in our environment?
{ SysFreeString is defined in Activex (at least from D5 on) }
uses ...., Activex;
....
function xxx(const Somestring: string; var ErrMsg: string): Cardinal;
var
WideErrMsg: PWideChar;
begin
....
{ the second argument is an "out" BSTR (OleString), it is returned as a
PWideChar }
Result := SomeCOMFunction(PChar(Somestring), WideErrMsg);
ErrMsg := OleStrToString(WideErrMsg);
SysFreeString(WideErrMsg);
end;


Danny
---
Bert
2003-10-21 20:42:50 UTC
Permalink
Alas, the problem is not quite clearly stated...here it is again, in "Danny"
terms:

function xxx(...)
var
AComObj: ISomeInterface;
WideErrMsg: WideChar;
begin
AComObj := CoSomeInterface.Create;
try
WideErrMsg := AComObj.SomeComPROPERTY;
ListBox1.Add(WideErrMsg);
finally
AComObj := nil;
end;
end;

Note that we are talking about a return value from a "property Get" function
rather than a parameter passed to/from a COM object's methods. Hence the
"property Get" is defined thus:

function Get_SomeComPROPERTY: widestring; safecall;
begin
Result := Call-to-something-that-returns-a-string-not-a-widestring;
end;

Anyway, the above leaks a BSTR (a.k.a. Widestring) in OleAut32.Dll.

Final word: No matter whether this gets answered or not (and I seriously
doubt it will). WideString has moved into my personal "another useless
geegaw" category. Plain ol' char * may be old and unsophisticated but
that's the route I take from here on.
Post by Danny Heijl
Post by Kathleen Beaumont
So, could you please post an example of the declaration and handling of
SysFreeString in Delphi so that we can try it out in our environment?
{ SysFreeString is defined in Activex (at least from D5 on) }
uses ...., Activex;
....
function xxx(const Somestring: string; var ErrMsg: string): Cardinal;
var
WideErrMsg: PWideChar;
begin
....
{ the second argument is an "out" BSTR (OleString), it is returned as a
PWideChar }
Result := SomeCOMFunction(PChar(Somestring), WideErrMsg);
ErrMsg := OleStrToString(WideErrMsg);
SysFreeString(WideErrMsg);
end;
Danny
---
Danny Heijl
2003-10-22 07:40:05 UTC
Permalink
Post by Bert
function Get_SomeComPROPERTY: widestring; safecall;
begin
Result := Call-to-something-that-returns-a-string-not-a-widestring;
end;
I think the problem is the implicit cast from BSTR to widestring.
A BSTR is nothing but a PWideChar to a memory area allocated with
Sys(Re)AllocString.

What about:

function Get_SomeComPROPERTY: widestring; safecall;
var
PResult: PWideChar;
begin
PResult := Call-to-something-that-returns-a-string-not-a-widestring;
Result := OleStrToString(PResult);
SysFreeString(PResult);
end;

Assuming normal character (not binary) data, because OleStrToString converts
to an AnsiString that gets converted back to a widestring in Result.

Danny
---

Loading...