仍然试图弄清楚ADODB的连接正在发生什么,以及为什么发生某些崩溃。
问题是我们的代码中发生内存泄漏:
void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}
经常调用此函数,因此是基本的内存泄漏。 用唯一的指针修复了它
void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
是的,但现在在ADODB的Recordset15 :: Close中开始发生访问权限冲突。
inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}
LaneControl.exe中0x679E653F(msado15.dll)的未处理异常: 0xC000041D:在用户期间遇到未处理的异常 回调。
因此,以正确的方式调用所有析构函数会导致新问题,因此记录集的某处已打开和关闭。
调试之后,事实证明,从两个不同的线程调用了getDetailConfig。
线程1
void updateIconStatus()
{
getDetailConfig();
}
线程ID 5bA8
线程2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}
线程ID 6A4C
因此,这2个线程调用getDetailConfig,其中关闭了在另一个线程上打开的记录集,并且释放了COM对象,而没有释放。
这是您无法在另一个线程上关闭ADO记录集的问题吗?它是一种竞赛条件吗? 在ADODB级别上出了什么问题?
答案 0 :(得分:1)
我认为这是比赛条件。
如果之前已经调用过getDetailConfig()
函数,然后两个线程都调用了getDetailConfig()
,则这可能导致两个线程同时调用析构函数(之前存在的对象的析构函数)({{ 1}}本质上不是线程安全的AFAIK。
然后,您需要确保交换指针的关键部分,例如,将std::unique_ptr
添加为类的成员(理想情况下应添加到成员列表的第一位,因此它的有效期长于std::mutex m_mutex;
成员),然后添加
m_displayConf
确保线程之间的交换被锁定。