//声明
variant_t varOptor,varOpTime;
WCHAR * szOperator=NULL;
WCHAR * szTime=NULL;
COleDateTime m_Time;
 _RecordsetPtr  pRecord;//.............................
//顺序1,正常,szOperator返回了人名,szTime返回了时间
varOptor=pRecord->GetCollect("operatorID");
varOpTime=pRecord->GetCollect("monitorTime");
szOperator=_bstr_t(varOptor);
szTime=_bstr_t(varOpTime);//顺序2,第4句执行后导致szOperator为"monitorTime"!即为我第三句的Record->GetCollect要查找的字段名常量!……
varOptor=pRecord->GetCollect("operatorID");
szOperator=_bstr_t(varOptor);
varOpTime=pRecord->GetCollect("monitorTime");
szTime=_bstr_t(varOpTime);
问题1:什么原因造成了这两个结果
问题2:有没有比_bstr_t转换WCHAR *类型更安全的方法

解决方案 »

  1.   

    函数段bool CEManHelperView::RecordTransform(const _RecordsetPtr & pRecord)
    {

    try
    {
    ///< 排除空数据集>
    if(static_cast<long>(pRecord->RecordCount)==0)
    {
    AfxMessageBox(L"没有数据!");
    return false;
    };
    ///</排除空数据集>
    ///< 确定定位为开始> if(static_cast<bool>(pRecord->BOF)==true)
    {
    AfxMessageBox(L"记录集没有定位到开始!");
    return false;
    };
    ///</确定定位为开始>
    ///< 时间计算>
    DWORD ulTimeBegin=GetTickCount();


    ///< 获取数据>
    WCHAR * szOperator;
    WCHAR * szTime=NULL;
    COleDateTime m_Time;
    variant_t varOptor,varOpTime; struct time_entry m_Entry; while(static_cast<bool>(pRecord->adoEOF)!=true)
    { varOptor=pRecord->GetCollect("operatorID");
    szOperator=varOptor;
    varOpTime=pRecord->GetCollect("monitorTime");
    szTime=_bstr_t(varOpTime);
    if(!m_Time.ParseDateTime(szTime))
    {
    AfxMessageBox(L"读取到无法解释的时间数据");
    return false;//临时措施
    //throw;//wait treat
    }
    //m_Entry.state=0;
    //m_Entry.time=m_Time;
    //m_OperatorTime[szOperator].push_back(time_entry(0,m_Time));
      pRecord->MoveNext();
    }
    ///</获取数据>  DWORD ulTimeEnd=GetTickCount();
    CString szClock;
    szClock.Format(L"%d",ulTimeEnd-ulTimeBegin);
    AfxMessageBox(szTime);
    ///</时间计算> return true;
    }
    catch(_com_error e)
    {
    CString   strComError;
    strComError.Format (  
    L"错误编号:   %08lx\n错误信息:   %s\n错误源:   %s\n错误描述:   %s ",   
    e.Error(),                                    
    e.ErrorMessage(),                      
    (WCHAR*) e.Source(),                 
    (WCHAR*)   e.Description()
    );     

    MessageBox(strComError,L"Error",MB_ICONEXCLAMATION);
    return false;
    }
    }追踪数据的话,两个variant_t的内容并没有因为两次调用顺序不同而有所变化……所以我只能猜测_bstr_t()的问题,而且,用CString替代WCHAR*直接赋值而不是用_bstr_t()的话也没有发生这个情况
      

  2.   

    追踪数据的话,两个variant_t的内容并没有因为两次调用顺序不同而有所变化……所以我只能猜测_bstr_t()的问题,而且,用CString替代WCHAR*直接赋值而不是用_bstr_t()的话也没有发生这个情况
    ==啥意思?variant_t的值正确,进行_bstr_t转换后错了?
      

  3.   

    szOperator=varOptor; 

    szOperator=_bstr_t(varOptor);用CString之后为了贴程序又改回去改漏了orz 
      

  4.   

    //==啥意思?variant_t的值正确,进行_bstr_t转换后错了?对,就是这样,variant_t里面储存的东西是正确的,由始至终不变化
    但是,经过_bstr_t输入到WCHAR *之后,随着_bstr_t的执行顺序不同,WCHAR*的内容变化了考虑过是指针的问题……但是,就算是指针问题WCHAR *不是应该指向variant_t里面的值或者szTime的内容,而不是一个L"monitorTime"字符串常量啊
      

  5.   

    size_t mbstowcs(
       wchar_t *wcstr,
       const char *mbstr,
       size_t count 
    );
    这个行不
      

  6.   

    更加诡异的事情: varOpTime=pRecord->GetCollect("monitorTime");
    szTime=_bstr_t(varOpTime);
    varOptor=pRecord->GetCollect("operatorID");
    szOperator=_bstr_t(varOptor);简单说,把1234变成3412,理论上……1234错的话3412应该还是会错的吧?结果正常……我现在已经无法言语我现在的感觉了,另外里面的数据提一下:
    varOpTime={"2009-06-04 09:28:59" VT_BSTR} _variant_t
    varOptor={"+00007" VT_BSTR} _variant_t
    szTime=0x0019bc84 "2009-06-04 09:28:59" wchar_t *
    szOperator=0x0019dc04 "+00007" wchar_t *不正常时:
    varOpTime={"2009-06-04 09:28:59" VT_BSTR} _variant_t
    varOptor={"+00007" VT_BSTR} _variant_t
    szTime=0x001a1624 "2009-06-04 09:28:59" wchar_t *
    szOperator=0x0019bff4 "monitorTime" wchar_t *现在考虑把程序里面所有_bstr_t全部重写成用CString转换,效率差点总比不知道什么原因出问题好……
      

  7.   

    换个方式
    CSting cOpeTime;
    cOpeTime = (LPCTSTR)(_bstr_t)pRecord->GetCollect("monitorTime");看看怎样?
      

  8.   

    问题出在这//顺序2,第4句执行后导致szOperator为"monitorTime"!即为我第三句的Record->GetCollect要查找的字段名常量!…… 
    varOptor=pRecord->GetCollect("operatorID"); 
    szOperator=_bstr_t(varOptor);    <== _bstr_t(varOptor) 构造了一个临时 _bstr_t 对象A,这句执行完,该对象被销毁,szOperator 实际上指向了一个无效的地址,不过这是这个地址里的内容还没有被覆盖掉
    varOpTime=pRecord->GetCollect("monitorTime"); szTime=_bstr_t(varOpTime); 
    // 再次构造一个临时对象B,该对象内部分配的地址恰好就是 varOptor 指向的地址(估计是内存池的原因),数据被覆盖// 当执行到这的时候 varOptor varOpTime 实际上指向的都是无效的地址
      

  9.   

    //顺序1,正常,szOperator返回了人名,szTime返回了时间 
    varOptor=pRecord->GetCollect("operatorID"); 
    varOpTime=pRecord->GetCollect("monitorTime"); 
    szOperator=_bstr_t(varOptor); 
    szTime=_bstr_t(varOpTime); 我估计顺序1也是不正常的
    当执行到 szTime=_bstr_t(varOpTime); 的时候 szOperator 应该也变成了时间用 CString 应该没问题varOptor=pRecord->GetCollect("operatorID"); 
    varOpTime=pRecord->GetCollect("monitorTime"); 
    CString strOptor = (BSTR)_bstr_t(varOptor); 
    CString strOpTime = (BSTR)_bstr_t(varOpTime); 
      

  10.   

    //>szOperator 实际上指向了一个无效的地址//这才是诡异啊,理论上,_bstr_t(var)的最终是:inline _bstr_t::_bstr_t(const _variant_t &var) 
        : m_Data(NULL)
    {
        if (V_VT(&var) == VT_BSTR) {
            *this = V_BSTR(&var);
            return;
        }    _variant_t varDest;
        varDest.ChangeType(VT_BSTR, &var);    *this = V_BSTR(&varDest);
    }
    其中_VT(&var) == VT_BSTR判断是判断是不是字符串
     *this = V_BSTR(&var);
    将自身地址变为var->bstrVal的地址,所以_bstr_t完全没有新建对象而且所指向的var的内容也没有变化过,但函数顺序变动后szoperatpr的内容却变化了……
      

  11.   

    inline _variant_t::_variant_t(const char* pSrc) 
    {
        V_VT(this) = VT_BSTR;
        V_BSTR(this) = _com_util::ConvertStringToBSTR(pSrc);
    }
    这函数执行完后szOperator被更改,这下我更搞不懂了,Var2的赋值干扰了Var1的内容?
      

  12.   

    *this = V_BSTR(&var); 
    将自身地址变为var->bstrVal的地址,这句不是这个意思你往下跟
    程序会运行到inline _bstr_t& _bstr_t::operator=(const wchar_t* s) 
    {
        _COM_ASSERT(s == NULL || static_cast<const wchar_t*>(*this) != s);    if (s == NULL || static_cast<const wchar_t*>(*this) != s)
        {
            _Free();        m_Data = new Data_t(s);
            if (m_Data == NULL) {
                _com_issue_error(E_OUTOFMEMORY);
            }
        }    return *this;
    }
      

  13.   

    *this = V_BSTR(&var);这句展开就是*this = (&var)->bstrVal;会调用 inline _bstr_t& _bstr_t::operator=(const wchar_t* s) 
      

  14.   

    >高手前传
    谢谢,没想到还有个运算符重载,不过现在定位问题到varOpTime=pRecord->GetCollect("monitorTime");
    跟踪到这里:
    inline _variant_t::_variant_t(const char* pSrc) 

        V_VT(this) = VT_BSTR; 
        V_BSTR(this) = _com_util::ConvertStringToBSTR(pSrc); 

    这段函数上,调用完后就变了,跟我想象中是_bstr_t产生问题不一样……
      

  15.   

    我写了一个测试程序
    _variant_t test(const _variant_t& t )
    {
    return t;
    }
    void CtestbstrDlg::OnBnClickedOk()
    {
    // TODO: Add your control notification handler code here
    OnOK(); WCHAR* p1, *p2;
    _variant_t v1, v2;
    v1 = test( _T("123") );
    p1 = _bstr_t(v1);
    v2 = test( _T("456") );
    p2 = _bstr_t(v2);
    }
      

  16.   


        WCHAR* p1, *p2;
        _variant_t v1, v2;
        v1 = test( _T("123") );
        p1 = _bstr_t(v1);        <== 调试到这的时候, p1 指向 0x0017073c, 这句执行完之后, 0x0017073c就被释放了, p1 指向一个无效地址
        v2 = test( _T("456") );  <== 调试到这,进入到 _variant_t 的构造函数
        p2 = _bstr_t(v2);
    inline _variant_t::_variant_t(const wchar_t* pSrc) 
    {
        V_VT(this) = VT_BSTR;    V_BSTR(this) = ::SysAllocString(pSrc);                    <== this 指针为0x0013616c, 但是 this->BSTR 指向 0x0017073c, 把 p1 的内容覆盖了    if (V_BSTR(this) == NULL && pSrc != NULL) {
                _com_issue_error(E_OUTOFMEMORY);
        }
    }
      

  17.   

    周六日不在没有结贴不好意思,谢谢marrco2005