在我的MFC (VC2010 SP1)项目中,我正在广泛使用第三方库在数据库中写入一些数据。这个库很旧(我发现它是为VS2005编译的),并使用_variant_t来处理数据。
在一个特殊的情况下,无论如何,我会尝试解释一种奇怪的行为:
// .h
struct myData
{
blastuff
CString strMyCode;
};
class MyClass
{
protected:
myData m_Foo;
};
// .cpp
// In OnInitDialog:
//...
TrdPartRecordset *pRS;
//...
pRS->GetFieldValue( _T("MyDBColumn"), m_Foo.strMyCode );现在,我完成了我的工作,当用户按OK时,是时候保存到数据库中了,这里开始出现问题:
// In OnOK
TrdPartRecordset *pRS;
//...
pRS->SetFieldValue( _T("MyDBColumn"), m_Foo.strMyCode );问题:如果我不修改m_Foo.strMyCode,我就没有任何问题。如果我修改它呢?好吧,如果m_Foo.strMyCode不包含任何号,那么仍然没有问题。相反,当我有一个数字时,我会得到一个严重的错误:
Unhandled exception at 0x77772d37 in Mosaico.exe: 0xC0000005: Access violation reading location 0x9d7077b7.这是试图读取已删除的位置。我在手表中签了m_Foo,它是正确的和有效的,所以我深入到了库源代码:
BOOL TrdPartyRecordset::SetFieldValue(LPCTSTR lpFieldName, CString strValue)
{
_variant_t vtFld;
if(!strValue.IsEmpty())
vtFld.vt = VT_BSTR;
else
vtFld.vt = VT_NULL;
vtFld.bstrVal = strValue.AllocSysString();
BOOL bret = PutFieldValue(lpFieldName, vtFld);
SysFreeString(vtFld.bstrVal);
return bret;
}发生的情况是,vtFld在SysFreeString之前是有效的,并且在它之后被销毁(我可以看到它一步一步地使用调试器),但是只有当我在strValue中有数字的时候。如果strValue是纯字母的,则不会发生这种情况。
我在互联网上搜索了一下,发现当你双倍发布一个资源时,这种错误就会发生,所以我对SysFreeString进行了评论,然后爆炸了:不再有崩溃了。
无论如何,他是一个比我更好的程序员,所以我想如果他把那个SysFreeString放进去,他有自己的理由,而且,这也是我程序中这个机制崩溃的唯一部分。
我的问题是:我是否丢失了注释掉SysFreeString的记忆?另一个:你有更好的解决方案吗?
发布于 2014-04-02 09:35:35
原因很简单:内存被释放了两次!
_variant_t有一个析构函数。将类型设置为VT_BSTR。您还会看到pojnter并键入到VT_BSTR
调用函数之后,您将再次释放内存,析构函数也会这样做。
代码应该如下所示:
_variant_t vtFld;
if(!strValue.IsEmpty())
vtFld = strValue;
else
vtFld.vt = VT_NULL;
return PutFieldValue(lpFieldName, vtFld);https://stackoverflow.com/questions/22791678
复制相似问题