Ici la ligne suivante alloue un nouveau BSTR
et remplit son pointeur vers le pointeur SL.Objects[]
.
SL.AddObject('my string', TObject(SysAllocString(PWideChar(WS))));
Ainsi, le va suivant une fuite définitivement mémoire:
var
WS: WideString;
begin
WS := PWideChar(SL.Objects[0]);
Voici une instance nouvelle WS sera alloué, de sorte que votre instance BSTR pointée par SL.Objects[0]
ne sera pas publié.
Et ce qui suit fonctionne par hasard:
SL.AddObject('my string', TObject(PWideChar(WS)));
La mémoire pointée par la mémoire tampon est PWideChar(WS)
contient encore à l'WS: WideString
instance précédente. Cela peut donc fonctionner ... jusqu'à ce que le tampon soit réutilisé et remplacé par d'autres données, et qu'un autre texte soit renvoyé, ou qu'un GPF aléatoire se produise. Par conseil: ne jamais tricher le système de type Delphi, en stockant autre chose qu'un TObject
dans une variable tapée TObject
... sauf si vous savez ce que vous faites. Ne jouez pas avec des pointeurs avant de savoir ce qu'ils sont et comment ils fonctionnent.
Je ne vois aucun avantage à stocker un WideString
dans une entrée TStrings.Object[]
!Changez votre structure de données: créez un vrai class
, en stockant votre chaîne. Ensuite, tout serait clair et propre:
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
La petite surcharge d'allocation d'une instance class
est négligeable en ce qui concerne une allocation de chaîne BSTR
, je peux vous dire. Et votre code serait définitivement plus propre et plus facile à entretenir/évoluer.
J'espérais laisser le système gérer la destruction de "l'objet" WideString. si j'utilise une structure de classe, j'ai besoin de libérer manuellement chaque objet (il n'y a pas d'OwnsObject dans D7 pour TStringList). Je ne suis toujours pas sûr si je dois ** libérer ** les chaînes qui sont allouées avec 'SysAllocString' ou le système peut s'occuper de ça pour moi? ... – zig
Oui, vous devez ** libérer ** des chaînes BSTR allouées par SysAllocString. –