2010-12-03 12 views
6

Was ist der richtige Weg, dies zu tun:_bstr_t Mit dem Parameter von * Typ BSTR in Funktion zu übergeben

_bstr_t description; 
errorInfo->GetDescription(&description.GetBSTR()); 

oder:

_bstr_t description; 
errorInfo->GetDescription(description.GetAddress()); 

Wo IError:GetDescription ist wie folgt definiert:

HRESULT GetDescription (BSTR *pbstrDescription); 

Ich weiß, ich könnte das leicht tun:

BSTR description= SysAllocString (L"Whateva")); 
errorInfo->GetDescription (&description); 
SysFreeString (description); 

Dank

Antwort

8

Der BSTR Verweis gezählt wird, ich bezweifle ernsthaft, dass richtig, wenn Sie GetAddress verwenden funktionieren wird(). Leider ist der Quellcode nicht verfügbar, um dies zu überprüfen. Ich habe es immer so gemacht:

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

+1, die Rede davon, dass der BSTR von _bstr_t von anderen Instanzen geteilt wird, verdränge mich von allem, was direkt zugewiesen werden könnte. –

+1

sollten Sie nicht 'Attach()' anstelle von Zuweisungsoperator verwenden? –

+0

Wie gezeigt, weist die Funktion 'GetDescription' Speicher auf' temp' mit 'SysAllocString' zu, und dieser Speicher wird nie freigegeben. Entweder müssen Sie 'SysFreeString (temp)' aufrufen oder sicherstellen, dass 'wrap' an diesen Speicher angehängt wird und diesen freigibt. – abelenky

5

Um Follow-up auf @ Hans Antwort - die geeignete Art und Weise die _bstr_t hängt davon ab, ob GetDescription kehren Sie ein BSTR, die Sie besitzen, oder ein zu konstruieren, die Speicher, den Sie don verweist Ich muss mich nicht befreien.

Ziel ist es, die Anzahl der Kopien zu minimieren, aber auch manuelle Rückrufe zu SysFreeString auf den zurückgegebenen Daten zu vermeiden. Ich würde den Code wie gezeigt ändern, um dies zu verdeutlichen:

BSTR temp = 0; 
HRESULT hr = p->GetDescription(&temp); 
if (SUCCEEDED(hr)) { 
    _bstr_t wrap(temp, false); // do not copy returned BSTR, which 
            // will be freed when wrap goes out of scope. 
            // Use true if you want a copy. 
    // etc.. 
} 
2

Eine späte Antwort, die möglicherweise nicht für frühere (oder spätere) Versionen von Visual Studio gilt; jedoch VS 12.0 hat die _bstr_t Implementierung inline, und offensichtlich eine interne Data_t Instanz wird mit einem m_RefCount von 1 beim Aufruf GetBSTR() auf einem ursprünglichen _bstr_t erstellt. So ist der _bstr_t Lebenszyklus in Ihrem ersten Beispiel sieht in Ordnung zu sein:

_bstr_t description; 
errorInfo->GetDescription(&description.GetBSTR()); 

Aber wenn _bstr_t verschmutzt ist, die vorhandenen internen m_wstr Zeiger überschrieben, den vorherigen Speicher undicht es referenziert.

Mit den folgenden kann ein schmutziger _bstr_t verwendet werden, da er zuerst über Assign(nullptr) gelöscht wurde. Die Überlast bietet auch die Möglichkeit, den Adressoperator anstelle von GetBSTR() zu verwenden;

BSTR *operator&(_bstr_t &b) { 
    b.Assign(nullptr); 
    return &b.GetBSTR(); 
} 

So, Ihr erstes Beispiel könnte stattdessen wie folgt aussehen:

_bstr_t description(L"naughty"); 
errorInfo->GetDescription(&description); 

Diese Auswertung basiert auf comutil.h von VS 12.0.