在 Windows C++ 代码中释放未持有的锁 CriticalSection
Getting Releasing unheld lock CriticalSection in Windows C++ code
我在下面的第二次尝试中收到警告“释放未持有的锁 'csCriticalSection'”。
这是我的代码,但没有所有 ADO 代码。我不知道为什么会收到此警告,因为如果 Execute()
函数失败,catch
将 运行 一个 LeaveCriticalSection
函数。如果 Execute()
函数成功,我调用 LeaveCriticalSection
.
#include <windows.h>
#include <synchapi.h>
#include <comdef.h>
#include <conio.h>
CRITICAL_SECTION csCriticalSection;
_ConnectionPtr connectioncreate = nullptr;
_RecordsetPtr recordset = nullptr;
int main()
{
InitializeCriticalSectionAndSpinCount(&csCriticalSection, 4000);
// *** all ADO code here ***
//
// *** all ADO code here ***
BOOL bRanLeaveCriticalSection = FALSE;
try
{
EnterCriticalSection(&csCriticalSection);
// Run an SQL command with ADO.
/*
connectioncreate->BeginTrans();
connectioncreate->Execute(sSQL.data(), nullptr, adCmdText);
connectioncreate->CommitTrans();
*/
LeaveCriticalSection(&csCriticalSection);
bRanLeaveCriticalSection = TRUE;
}
catch (CONST _com_error& err)
{
connectioncreate->CommitTrans();
if (bRanLeaveCriticalSection == FALSE)
LeaveCriticalSection(&csCriticalSection);
}
try
{
// From compiler at the next line "if (recordset)":
// Warning C26117 Releasing unheld lock 'csCriticalSection'
if (recordset)
if (recordset->State == adStateOpen)
recordset->Close();
}
catch (CONST _com_error& err)
{
err;
}
_getch();
}
任何人都可以帮助我了解我收到此警告的原因以及如何修复它?
您没有在使用前初始化 csCriticalSection
,例如:
...
CRITICAL_SECTION csCriticalSection;
...
int main()
{
InitializeCriticalSection(&csCriticalSection); // <-- ADD THIS
...
DeleteCriticalSection(&csCriticalSection); // <-- ADD THIS
}
而且,您真的根本不应该使用 bRanLeaveCriticalSection
,这只是糟糕的代码设计。
您可以改用 __try/__finally
块(如果您的编译器支持的话),例如:
...
CRITICAL_SECTION csCriticalSection;
...
int main()
{
...
try
{
EnterCriticalSection(&csCriticalSection);
__try
{
// Run an SQL command with ADO.
}
__finally
{
LeaveCriticalSection(&csCriticalSection);
}
}
catch (CONST _com_error& err)
{
...
}
...
}
然而,最好的选项是使用 RAII 包装器,让它为您调用 EnterCriticalSection()
和 LeaveCriticalSection()
,例如:
struct CRITICAL_SECTION_LOCK
{
CRITICAL_SECTION &m_cs;
CRITICAL_SECTION_LOCK(CRITICAL_SECTION &cs) : m_cs(cs) {
EnterCriticalSection(&m_cs);
}
~CRITICAL_SECTION_LOCK() {
LeaveCriticalSection(&m_cs);
}
};
...
CRITICAL_SECTION csCriticalSection;
int main()
{
...
try
{
CRITICAL_SECTION_LOCK lock(csCriticalSection);
// Run an SQL command with ADO.
}
catch (CONST _com_error& err)
{
...
}
...
}
或者更好,使用 C++ std::mutex
instead, with a proper RAII lock such as std::lock_guard
,例如:
#include <mutex>
std::mutex mtx;
...
int main()
{
try
{
std::lock_guard<std::mutex> lock(mtx);
// Run an SQL command with ADO.
}
catch (CONST _com_error& err)
{
...
}
...
}
我在下面的第二次尝试中收到警告“释放未持有的锁 'csCriticalSection'”。
这是我的代码,但没有所有 ADO 代码。我不知道为什么会收到此警告,因为如果 Execute()
函数失败,catch
将 运行 一个 LeaveCriticalSection
函数。如果 Execute()
函数成功,我调用 LeaveCriticalSection
.
#include <windows.h>
#include <synchapi.h>
#include <comdef.h>
#include <conio.h>
CRITICAL_SECTION csCriticalSection;
_ConnectionPtr connectioncreate = nullptr;
_RecordsetPtr recordset = nullptr;
int main()
{
InitializeCriticalSectionAndSpinCount(&csCriticalSection, 4000);
// *** all ADO code here ***
//
// *** all ADO code here ***
BOOL bRanLeaveCriticalSection = FALSE;
try
{
EnterCriticalSection(&csCriticalSection);
// Run an SQL command with ADO.
/*
connectioncreate->BeginTrans();
connectioncreate->Execute(sSQL.data(), nullptr, adCmdText);
connectioncreate->CommitTrans();
*/
LeaveCriticalSection(&csCriticalSection);
bRanLeaveCriticalSection = TRUE;
}
catch (CONST _com_error& err)
{
connectioncreate->CommitTrans();
if (bRanLeaveCriticalSection == FALSE)
LeaveCriticalSection(&csCriticalSection);
}
try
{
// From compiler at the next line "if (recordset)":
// Warning C26117 Releasing unheld lock 'csCriticalSection'
if (recordset)
if (recordset->State == adStateOpen)
recordset->Close();
}
catch (CONST _com_error& err)
{
err;
}
_getch();
}
任何人都可以帮助我了解我收到此警告的原因以及如何修复它?
您没有在使用前初始化 csCriticalSection
,例如:
...
CRITICAL_SECTION csCriticalSection;
...
int main()
{
InitializeCriticalSection(&csCriticalSection); // <-- ADD THIS
...
DeleteCriticalSection(&csCriticalSection); // <-- ADD THIS
}
而且,您真的根本不应该使用 bRanLeaveCriticalSection
,这只是糟糕的代码设计。
您可以改用 __try/__finally
块(如果您的编译器支持的话),例如:
...
CRITICAL_SECTION csCriticalSection;
...
int main()
{
...
try
{
EnterCriticalSection(&csCriticalSection);
__try
{
// Run an SQL command with ADO.
}
__finally
{
LeaveCriticalSection(&csCriticalSection);
}
}
catch (CONST _com_error& err)
{
...
}
...
}
然而,最好的选项是使用 RAII 包装器,让它为您调用 EnterCriticalSection()
和 LeaveCriticalSection()
,例如:
struct CRITICAL_SECTION_LOCK
{
CRITICAL_SECTION &m_cs;
CRITICAL_SECTION_LOCK(CRITICAL_SECTION &cs) : m_cs(cs) {
EnterCriticalSection(&m_cs);
}
~CRITICAL_SECTION_LOCK() {
LeaveCriticalSection(&m_cs);
}
};
...
CRITICAL_SECTION csCriticalSection;
int main()
{
...
try
{
CRITICAL_SECTION_LOCK lock(csCriticalSection);
// Run an SQL command with ADO.
}
catch (CONST _com_error& err)
{
...
}
...
}
或者更好,使用 C++ std::mutex
instead, with a proper RAII lock such as std::lock_guard
,例如:
#include <mutex>
std::mutex mtx;
...
int main()
{
try
{
std::lock_guard<std::mutex> lock(mtx);
// Run an SQL command with ADO.
}
catch (CONST _com_error& err)
{
...
}
...
}