2010-12-03 15 views
6

¿Cuál es la forma correcta de hacer esto:Usando _bstr_t pasar parámetro de tipo BSTR * en función de

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

o:

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

donde se define IError:GetDescription como:

HRESULT GetDescription (BSTR *pbstrDescription); 

Sé que podría hacer esto fácilmente:

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

Gracias

Respuesta

8

El BSTR se cuenta referencia, tengo serias dudas de que funcionarán correctamente si se utiliza GetAddress(). Lamentablemente, el código fuente no está disponible para verificarlo dos veces. Siempre lo he hecho así:

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

+1, la charla del BSTR de _bstr_t compartida por otras instancias me desactivó cualquier cosa que pudiera asignársele directamente. –

+1

¿no debería usar 'Adjuntar()' en lugar de operador de asignación? –

+0

Como se muestra, la función 'GetDescription' asigna memoria a' temp' con 'SysAllocString', y esa memoria nunca se libera. O bien, debe llamar a 'SysFreeString (temp)', o asegurarse de que 'wrap' se una a esa memoria y la libere. – abelenky

5

Para dar seguimiento a @ respuesta de Hans - la forma adecuada para construir el _bstr_t depende de si GetDescription le devuelve una BSTR que es el propietario, o uno que hace referencia a la memoria que Don tienes que liberar.

El objetivo aquí es minimizar el número de copias, pero también evitar cualquier llamada manual al SysFreeString en los datos devueltos. Me gustaría modificar el código como se muestra para aclarar esto:

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

Una respuesta tardía que no puede aplicarse a las versiones anteriores (o posterior) de Visual Studio; sin embargo, VS 12.0 tiene la implementación _bstr_t en línea, y evidentemente se crea una instancia interna Data_t con un m_RefCount de 1 al llamar al GetBSTR() en una virgen _bstr_t. Por lo que el ciclo de vida _bstr_t en su primer ejemplo parece estar bien:

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

Pero si _bstr_t es sucio, se sobrescribe el m_wstr puntero interno existente, fugas de la memoria anterior se hace referencia.

Al usar el siguiente operator&, se puede usar un _bstr_t sucio ya que se borró primero a través de Assign(nullptr). La sobrecarga también proporciona la comodidad de utilizar el operador de dirección en lugar de GetBSTR();

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

Así, el primer ejemplo podría en cambio ser similar al siguiente:

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

Esta evaluación se basa en comutil.h de VS 12.0.

Cuestiones relacionadas