locked
Wierd Behaviour of DCOM and SysAllocString/SysFreeString in different platforms

    Pergunta

  • I am a process of developing a COM/DCOM Server which handles the Data in/out from a Database. As it involves more and more data, the COM best practices tend me to use the BSTR as the De-facto String for the transactions. I am developing all the components in Win XP where all the things went smooth and clean. The code is

    STDMETHODIMP CApplication::GetAllAddressByName(BSTR bstrParamName, VARIANT *vAdddresses)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState())
    
    	//check the Database server connection
    
    	COleSafeArray saAddress;
    	HRESULT hr;
    
    	// Prepare the SQL Strings dan Query the DB
    
    	long lRecCount = table.GetRecordCount();
    
    	 if (lRecCount > 0)
    	 {
    		//create one dimension safe array for putting  details
    		saAddress.CreateOneDim(VT_DISPATCH,lRecCount);
    
    		IAddress *pIAddress = NULL; 
    		//retrieve details 
    		for(long iRet = table.MoveFirst(),iCount=0; !iRet; iRet = table.MoveNext(),iCount++)
    		{
    			CComObject<CAddress> *pAddress;
    			hr = CComObject<CAddress>::CreateInstance(&pAddress);
    			if (SUCCEEDED(hr))
    			{   
    				BSTR bstrStreet = ::SysAllocString(table.m_pRecordData->Street);
    				pAddress->put_StreetName(bstrStreet);
    
    				BSTR bstrCity = ::SysAllocString(table.m_pRecordData->City);
    				pAddress->put_CityName(bstrCity);
    				
    				//Here is the Problem Comes
    				::SysFreeString(bstrStreet);
    				::SysFreeString(bstrCity);
    			}
    			hr = pAddress->QueryInterface(IID_IAddress, (void**)&pIAddress);
    			if(SUCCEEDED(hr)) 
    			{
    				saAddress.PutElement(&iCount,pIAddress); 
    			}
    		}
    		*vAdddresses=saAddress.Detach(); 
    	}
    	table.Close(); 
    	return S_OK;
    }
    
    
    STDMETHODIMP CAddress::put_CityName(BSTR bstrCityName)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState())
        // m_sCityName is of CComBSTR Type
        m_sCityName.Empty();//free the old string 
        m_sCityName = ::SysAllocString(bstrCityName);//create the memory for the new string
        return S_OK;
    }


    The problem raised when the same was deployed in the Win 7, the DCOM Server Application went on intermittent crashes. On using the DebugDiag and analysing the crash dumps generated, the crash pointed the SysFreeString() is causing the crash and the debugging in Win 7 provided the error info as

    "Windows has triggered a breakpoint in dllhost.exe.

    This may be due to a corruption of the heap, and indicates a bug in dllhost.exe or any of the DLLs it has loaded."


    The Setting for the DCOM Server as Follows:


    Security Tab:

    No Authorization

    Security Level : Perform access checks only at the Process Level

    No Software Restriction Policy

    Authentication Level for Calls : Packet

    Impersonation Level: Impersonate


    Identity:

    In XP it ran fine in both System Account- Interactive User and in This User-[An Administrator User]


    In 7 Failed in both


    Activation:

    As Server Application and not as NT Service


    Queuing:

    Non Queued

    MSMQ Message Authentication is set to Authenticate messages if authentication level for calls



    Is there anything missed in the setting or code? Any platform specific code need to be incorporated?


    N.B: The Crash is consistent in all the Win 7 and No crash in all Win XP


    Sathish Guru V

    segunda-feira, 5 de março de 2012 17:44

Respostas

  •                BSTR bstrStreet = ::SysAllocString(table.m_pRecordData->Street);

    Do away with explicitly calling SysAllocString/SysFreeString, and use
    one of the smart BSTR wrappers such as CComBSTR or _bstr_t.

               hr = pAddress->QueryInterface(IID_IAddress, (void**)&pIAddress);
               if(SUCCEEDED(hr))            {
                   saAddress.PutElement(&iCount,pIAddress);            }

    What's releasing pIAddress? Use CComQIPtr instead.

       // m_sCityName is of CComBSTR Type
       m_sCityName.Empty();//free the old string    m_sCityName = ::SysAllocString(bstrCityName);//create the memory for the new string

    As you're using a smart BSTR object, you don't need to do that
    free/alloc, that's why it's a smart object.

    Dave

    • Marcado como Resposta Rob Pan terça-feira, 13 de março de 2012 09:25
    segunda-feira, 5 de março de 2012 19:10