仍在尝试弄清ADODB的连接正在发生什么,以及为什么发生某些崩溃。

问题是我们的代码中发生内存泄漏:

void getDetailConfig()
{
    m_displayConf = new TestDetailDisplayCfg();
}

通常会调用此函数,因此是基本的内存泄漏。
用唯一的指针修复了它
void getDetailConfig()
{
    m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}

是的,但是现在在ADODB的Recordset15::Close内部开始发生违反acces的行为。
inline HRESULT Recordset15::Close ( ) {
    HRESULT _hr = raw_Close();
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _hr;
}



因此,以正确的方式调用所有析构函数会导致新问题,因此某个位置的记录集已打开和关闭。

调试之后,事实证明,从两个不同的线程调用了getDetailConfig。

线程1
void updateIconStatus()
{
    getDetailConfig();
}

c&#43;&#43; - ADODB记录集内的访问冲突关闭-LMLPHP

线程ID 5bA8

线程2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
    m_CurrentDialog->getDetailConfig();
}

c&#43;&#43; - ADODB记录集内的访问冲突关闭-LMLPHP

线程ID 6A4C

因此,这两个线程调用getDetailConfig,其中记录集已关闭,而该记录集是在另一个线程上打开的,并且COM对象已释放,而没有释放。

这是您无法在另一个线程上关闭ADO记录集的问题吗?它是一种竞赛条件吗?
在ADODB级别上出了什么问题?

最佳答案

我认为这是比赛条件。

如果getDetailConfig()函数已经被调用过,然后两个线程都调用getDetailConfig(),这可能导致两个线程同时调用析构函数(之前存在的对象的析构函数)(std::unique_ptr本质上不是线程安全的AFAIK)。

然后,您需要确保交换指针的关键部分,例如,将std::mutex m_mutex;添加为类的成员(理想情况下应添加到成员列表的第一位,因此其有效期比m_displayConf成员更长),然后添加

void getDetailConfig()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}

确保线程之间的交换被锁定。

10-08 05:20