2009-03-12 8 views
2

Je suit bloc de codeProblème d'accès à l'aide SafeArray CComVariant

///////////////////////////////////// 
CComVariant newVal; 

//pass the CComVariant and get the strings array!!! 
GetStrList(newVal); 
USES_CONVERSION; 

if (((newVal.vt & VT_ARRAY) == VT_ARRAY) && ((newVal.vt & VT_BSTR) == VT_BSTR)) 
{ 
SAFEARRAY* paArray = newVal.parray; 
BSTR * str = NULL; 
SafeArrayAccessData(paArray, (void**)&str); 

SafeArrayUnaccessData(paArray); 

long lLBound = 0; 
long lUBound = 0; 
long nCount = 0; 

if (FAILED(SafeArrayGetLBound(paArray, 1, &lLBound)) || 
    FAILED(SafeArrayGetUBound(paArray, 1, &lUBound))) 
{ 
    ASSERT(false); 
    return FALSE; 
} 


nCount = (lUBound - lLBound + 1); 
for (int i = 0 ; i < nCount ; i++) 
{   
    m_cstrList.AddString(W2T(str[i]));     
} 
//SafeArrayDestroy(paArray); ---> is it required here??? 

} 

///////////////////////////////////// 

méthode returing les tableaux sécurisés

HRESULT GetStrList(VARIANT *pVal) 
{ 
USES_CONVERSION; 

if (!pVal) 
    return E_FAIL; 

SAFEARRAYBOUND bound[1]; //single dimension array 
bound[0].lLbound = 0; 
bound[0].cElements = 10; 

SAFEARRAY * A = SafeArrayCreate(VT_BSTR, 1, bound); 

BSTR * str = NULL; 
SafeArrayAccessData(A, (void**)&str); 

//user wants the NT view OPC drivers list. 
for (int i=0;i<10;i++) 
{  
    str[i] = SysAllocString(T2W(mystrings[i]));  
} 


VariantInit(pVal); 
pVal->vt  = VT_ARRAY | VT_BSTR; 
pVal->parray = A; 

SafeArrayUnaccessData(A); 
A = NULL; 

return S_OK; 
} 

Mon doute est, au-dessus premier bloc de code a des fuites de mémoire? Est-ce que le CComVariant s'occupe lui-même de tout le nettoyage? ou dois-je également faire manuellement SafeArrayDestroy(paArray);

Merci à l'avance!

Répondre

3

CComVariant destructor appelle VariantClear() qui libère tout ce que la variante était en train d'encapsuler, y compris les tableaux. Une mise en garde: le tableau ne doit pas être verrouillé au moment où VariantClear() est appelé. Cela signifie que si une exception est levée après SafeArrayAccessData() mais avant SafeArrayUnaccessData(), ce dernier ne sera pas appelé et VariantClear() ne libérera pas de ressources.

Par conséquent, il est préférable d'écrire une classe de parenthèses pour l'appariement des appels SafeArrayAccessData() et SafeArrayUnaccessData().

+0

si je fais SafeArrayDestroy (paArray); alors je ne reçois pas de plantages. Selon vous, CComVariant devrait aussi détruire le même tableau, en essayant de détruire le tableau qui est déjà détruit. – coolcake

+0

Eh bien, oui. Peut-être qu'il ne plante pas juste par accident, mais MSDN dit que VariantClear() libère des tableaux non verrouillés. Donc essayer de les libérer manuellement conduirait à une double libération qui n'est pas bonne du tout. – sharptooth

+0

Donc, ne devrais-je pas utiliser SafeArrayDestroy pour CComVariant? – coolcake

Questions connexes