c++ - 关于 MFC 库中的 _variant_t 类型

标签 c++ visual-studio-2010 mfc variant

在我的 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 确实NOT 包含任何 数字,仍然没有问题。 相反,当我有一个数字时,我得到一个讨厌的错误:

Unhandled exception at 0x77772d37 in Mosaico.exe: 0xC0000005: Access violation reading location 0x9d7077b7.

这是试图读取已删除的位置。我检查了 watch 中的 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 是纯字母顺序时,不会发生这种情况。

我在 Internet 上搜索了一下,发现当您双重释放资源时会发生这种错误,所以我注释掉了 SysFreeString 并且炸药爆炸了:不再发生崩溃。

无论如何,他是一个比我更好的程序员,所以我猜如果他放那个 SysFreeString 是有他的理由的,而且,这是我程序中这个机制崩溃的唯一部分。

我的问题是:注释掉 SysFreeString 后我会失去内存吗? 另一个:你们有更好的解决方案吗?

最佳答案

原因很简单: 内存被释放了两次!

_variant_t 有一个析构函数。将类型设置为 VT_BSTR。您还会看到指针并键入 VT_BSTR

在您调用的函数之后,您再次释放内存,析构函数执行相同的操作。

代码应该是这样的:

_variant_t vtFld;
if(!strValue.IsEmpty())
    vtFld = strValue;
else
    vtFld.vt = VT_NULL;
return PutFieldValue(lpFieldName, vtFld);

关于c++ - 关于 MFC 库中的 _variant_t 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22791678/

相关文章:

c++ - 对静态成员的 undefined reference

c++ - 如果atomic_compare_exchange在它自己的线程上不是原子的,它如何实现锁?

visual-studio-2010 - 从 DLL 中去除特定符号

c# - 控制台应用程序的多个配置文件

c++ - C++ 是否有像 npm、pip、gem 等这样的包管理器?

c++ - 了解 visual studio 2010 中的编译器选项差异和严格的 C++ 合规性

c++ - MFC CListCtrl::SetItemText() 不工作

c++ - CDialog更新输入框值

c++ - 将 CDialog 分成两个不同背景的区域(里面的目标图片)

C++ 无效比较器