//声明
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 *类型更安全的方法
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 *类型更安全的方法
{
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()的话也没有发生这个情况
==啥意思?variant_t的值正确,进行_bstr_t转换后错了?
是
szOperator=_bstr_t(varOptor);用CString之后为了贴程序又改回去改漏了orz
但是,经过_bstr_t输入到WCHAR *之后,随着_bstr_t的执行顺序不同,WCHAR*的内容变化了考虑过是指针的问题……但是,就算是指针问题WCHAR *不是应该指向variant_t里面的值或者szTime的内容,而不是一个L"monitorTime"字符串常量啊
wchar_t *wcstr,
const char *mbstr,
size_t count
);
这个行不
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转换,效率差点总比不知道什么原因出问题好……
CSting cOpeTime;
cOpeTime = (LPCTSTR)(_bstr_t)pRecord->GetCollect("monitorTime");看看怎样?
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 实际上指向的都是无效的地址
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);
: 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的内容却变化了……
{
V_VT(this) = VT_BSTR;
V_BSTR(this) = _com_util::ConvertStringToBSTR(pSrc);
}
这函数执行完后szOperator被更改,这下我更搞不懂了,Var2的赋值干扰了Var1的内容?
将自身地址变为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;
}
谢谢,没想到还有个运算符重载,不过现在定位问题到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产生问题不一样……
_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);
}
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);
}
}