ADODB 记录集中的访问冲突关闭
access violation inside ADODB recordset Close
仍在尝试弄清楚 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;
}
Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.
因此以正确的方式调用所有析构函数导致了一个新问题,在某处打开和关闭了记录集。
调试后发现 getDetailConfig 是从两个不同的线程调用的。
线程 1
void updateIconStatus()
{
getDetailConfig();
}
线程 ID 5bA8
线程2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}
线程 ID 6A4C
所以这 2 个线程调用 getDetailConfig,其中一个记录集被关闭,而该记录集在另一个线程上打开,并且 COM 对象被释放等等。
这是您无法在另一个线程上关闭 ADO 记录集的问题吗?它更像是一种竞争条件吗?
ADODB 级别出现什么问题?
我认为这是一个竞争条件。
如果之前已经调用了 getDetailConfig()
函数,然后两个线程都调用了 getDetailConfig()
,这可能会导致两个线程同时调用(之前存在的对象的)析构函数 ( std::unique_ptr
本质上不是线程安全的 AFAIK)。
然后您需要确保指针交换的关键部分,例如将 std::mutex m_mutex;
添加为您的 class 的成员(理想情况下添加到成员列表中的第一位,以便它比 m_displayConf
成员保持有效)然后添加
void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
确保线程之间的交换被锁定。
仍在尝试弄清楚 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;
}
Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe: 0xC000041D: An unhandled exception was encountered during a user callback.
因此以正确的方式调用所有析构函数导致了一个新问题,在某处打开和关闭了记录集。
调试后发现 getDetailConfig 是从两个不同的线程调用的。
线程 1
void updateIconStatus()
{
getDetailConfig();
}
线程 ID 5bA8
线程2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}
线程 ID 6A4C
所以这 2 个线程调用 getDetailConfig,其中一个记录集被关闭,而该记录集在另一个线程上打开,并且 COM 对象被释放等等。
这是您无法在另一个线程上关闭 ADO 记录集的问题吗?它更像是一种竞争条件吗? ADODB 级别出现什么问题?
我认为这是一个竞争条件。
如果之前已经调用了 getDetailConfig()
函数,然后两个线程都调用了 getDetailConfig()
,这可能会导致两个线程同时调用(之前存在的对象的)析构函数 ( std::unique_ptr
本质上不是线程安全的 AFAIK)。
然后您需要确保指针交换的关键部分,例如将 std::mutex m_mutex;
添加为您的 class 的成员(理想情况下添加到成员列表中的第一位,以便它比 m_displayConf
成员保持有效)然后添加
void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
确保线程之间的交换被锁定。