9
votes

Utilisation de _BSTR_T pour passer des paramètres de type BSTR * en fonction

Quelle est la bonne façon de faire cela: xxx

ou: xxx

iError: getDescription est défini comme suit: xxx

Je sais que je pouvais facilement faire cela: xxx

merci


0 commentaires

5 Réponses :


9
votes

La référence BST est comptée, je doute sérieusement que cela fonctionnerait bien si vous utilisez GetAddress (). Malheureusement, le code source n'est pas disponible pour vérifier cela. Je l'ai toujours fait comme ceci:

BSTR temp = 0;
HRESULT hr = p->GetDescription(&temp);
if (SUCCEEDED(hr)) {
    _bstr_t wrap(temp, FALSE);
    // etc..
}


3 commentaires

+1, la conversation de l'étant partagée de _BSTR_T ''s BSTR partageant d'autres instances me pose tout ce qui pourrait s'identifier directement à cela.


Ne devriez-vous pas utiliser joindre () au lieu de l'opérateur d'attribution?


Comme indiqué, la fonction getDescription attribue la mémoire à TEMP avec sysallocstring , et cette mémoire n'est jamais libérée. Vous devez appeler sysfreestring (TEMP) ou assurez-vous que enveloppe attache à cette mémoire et libère-le.



5
votes

Suivi de la réponse de @ Hans - Le moyen approprié de construire le _bstr_t dépend de si getDescription vous retourne un btr que vous possédez , ou un qui fait référence à la mémoire que vous n'avez pas à libérer.

Le but ici est de minimiser le nombre de copies, mais d'éviter également les appels manuels vers SysfreString sur les données renvoyées. Je modifierais le code comme indiqué pour clarifier ceci: xxx


0 commentaires

3
votes

une réponse tardive qui peut ne pas s'appliquer aux versions antérieures (ou ultérieures) de Visual Studio; cependant, Vs 12.0 a le _bstr_t implémentation en ligne, et évidemment d'une instance interne data_t est créée avec un m_refcount de 1 lorsque vous appelez getSTR () sur une vierge _bstr_t . Donc le _bstr_t Le cycle de vie dans votre premier exemple semble aller bien: xxx

mais si _bstr_t est sale, le code interne existant M_WSTR Le pointeur sera écrasé, fuyant la mémoire précédente qu'elle a référencée.

à l'aide des opérateurs suivants et , _bstr_t peut être utilisé étant donné qu'il est d'abord effacé via Attribuer (nullptr) . La surcharge fournit également la commodité d'utiliser l'opérateur d'adresse au lieu de getbstr () ; xxx

Donc, votre premier exemple pourrait plutôt ressembler à ce qui suit : xxx

Cette évaluation était basée sur comute.h de VS 12.0.


1 commentaires

Merci beaucoup pour cela, j'ai voulu quelque chose comme cet opérateur pendant les vingt dernières années.



0
votes

Ma réponse est aussi tardive. Supposons que vous ayez la signature HRESULT PutDescription (BSTR NewDescription); code>. Dans ce cas, procédez comme suit xxx pré>

par les règles de COM, la fonction putdescription code> n'est pas autorisée à modifier ou même détruire le code transduit code >. P>

pour l'opposé HRESULT getDescription (BSTR * PactualDescription); Code> Passer une VIRGIN _BSTR_T CODE> au moyen de la fonction getAddress () : P>

BSTR Bst = ::SysAllocString(L"Who would do that?");
_bstr_t GetDescr;
GetDescr.Attach(Bst);//GetDescr wraps Bst, no copying!
HRESULT hr = GetDescription(GetDescr.GetAddress());


0 commentaires

0
votes

_BSTR_T (et son CCOMBSTR ATL SIBLY) sont des propriétaires de ressources de BSTR. SPYPY DU CODE Il semble que "GetAddress" soit spécialement conçu pour le cas d'utilisation de la fonction de travail avec des paramètres de sortie BSTR où il est prévu que le client libère le BSTR.

Utilisation de 'getAddress ()' n'est pas équivalent à l'utilisation de '& getbstr ( ) 'Si le _BSTR_T possède déjà un BSTR. Etats MSDN: "libère toute chaîne existante et renvoie l'adresse d'une chaîne nouvellement allouée.". xxx

cavalier: Ce cas d'utilisation spécifique de "getAddress" n'est pas indiqué dans le Documentation; C'est ma déduction de regarder le code source et de l'expérience avec sa partie compteur ATL CCOMBSTR.


0 commentaires