Here the following line does allocate a new BSTR
and fill its pointer to the SL.Objects[]
pointer.
SL.AddObject('my string', TObject(SysAllocString(PWideChar(WS))));
So the following will definitively leak memory:
var
WS: WideString;
begin
WS := PWideChar(SL.Objects[0]);
Here a new WS instance will be allocated, so your BSTR instance pointed by SL.Objects[0]
won't be released.
And the following is working by chance:
SL.AddObject('my string', TObject(PWideChar(WS)));
The memory pointed by the PWideChar(WS)
memory buffer is still containing to the previous WS: WideString
instance. So is may work... until the buffer is re-used and overriden by some other data, and another text is returned, or a random GPF occurs.
By advice: never cheat the Delphi type system, storing something else than a TObject
in a variable typed as TObject
... unless you know what you are doing. Don't play with pointers until you know what they are and how they work.
I do not see any benefit of storing a WideString
within a TStrings.Object[]
entry! Change your data structure: create a true class
, storing your string. Then everything would be clear and clean:
type
TMyStoreWS = class
protected
fText: WideString;
public
constructor Create(const aText: WideString); virtual;
property Text: WideString read fText write fText;
end;
constructor TMyStoreWS.Create(const aText: WideString);
begin
inherited Create;
fText := aText;
end;
...
SL.AddObject('my string', TMyStoreWS.Create(aText)); // clean
...
ShowMessage(SL.Objects[0].Text); // clean
SL.Objects[0].Free; // don't forget to release
The small overhead of allocating a class
instance is negligeable in regard to a BSTR
string allocation, I can tell you. And your code would definitively be cleaner and easier to maintain/evolve.
SysAllocString
or the system can take care of that for me?... – Melo