gpt4 book ai didi

c++ - 代码在 WinDbg 上运行良好,但没有它就很奇怪

转载 作者:太空宇宙 更新时间:2023-11-04 14:29:41 27 4
gpt4 key购买 nike

我正在调试 WinDbg 的一个问题,我可以始终如一地生成该问题。问题是当我用 WinDbg 运行可执行文件进行调试时,问题无法重现。可能是什么原因?

这是行为不同的代码:

CWnd* pWnd = GetDlgItem(IDOKCANCEL);
if(pWnd)
{
CString sOK;
sOK.LoadString(IDS_OK);
pWnd->SetWindowText(sOK);
}

这里,当我使用 WinDbg 运行时,按钮文本会正确更新,但当我正常运行时,它不会更新(这是错误)。

更新

正如我在评论中所说,问题不在于上面的代码,因为它甚至没有被调用。该操作在工作线程中完成,该工作线程将更新消息发送到此对话框。执行上述代码的最终消息永远不会发送,因此永远不会执行上述代码。

为什么工作线程不发送这条消息很有趣。打开数据库时,它会锁定在关键部分。 WinDbg 告诉我主线程是该关键部分的所有者,但我无法从调用堆栈或任何其他方式看到它未能解锁关键部分的位置。

使问题复杂化的是,如果我使用调试器运行它,它工作正常。我添加了日志输出,但它也开始与此更改一起正常工作。

我可以用调试器捕获它的唯一方法是在正常模式下运行它,产生问题,然后附加调试器,它显示它已锁定在关键部分。它显示主线程是该关键部分的所有者,但不清楚为什么它处于锁定状态。关键部分只是在一个函数中被锁定和解锁,并且它在外面。

更新 2

我只在整个项目的一个文件中使用关键部分,并且只有两个函数(当它打开数据库和记录集时)。

BOOL CADODatabase::Open(LPCTSTR lpstrConnection, LPCTSTR lpstrUserID, LPCTSTR lpstrPassword)
{
CString database = GetSourceDatabase( lpstrConnection, NULL );

// get the appropriate critical section based on database
g_dbCriticalSection = GetDbCriticalSection( database );

if( g_dbCriticalSection)
g_dbCriticalSection->Lock();

HRESULT hr = S_OK;

if(IsOpen())
Close();

if(wcscmp(lpstrConnection, _T("")) != 0)
m_strConnection = lpstrConnection;

ASSERT(!m_strConnection.IsEmpty());

try
{
if(m_nConnectionTimeout != 0)
m_pConnection->PutConnectionTimeout(m_nConnectionTimeout);
hr = m_pConnection->Open(_bstr_t(m_strConnection), _bstr_t(lpstrUserID), _bstr_t(lpstrPassword), NULL);

if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();

return hr == S_OK;
}
catch(_com_error &e)
{
dump_com_error(e);

if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();

return FALSE;
}
}

第二个函数还有其他明显的缺陷,但请忽略它,它是遗留代码。

BOOL CADORecordset::Open(_ConnectionPtr mpdb, LPCTSTR lpstrExec, int nOption)
{
BSTR bstrConnString;
m_pConnection->get_ConnectionString(&bstrConnString);
CString database = GetSourceDatabase( bstrConnString, m_pConnection );

g_dbCriticalSection = GetDbCriticalSection( database );

if( g_dbCriticalSection)
g_dbCriticalSection->Lock();

Close();

if(wcscmp(lpstrExec, _T("")) != 0)
m_strQuery = lpstrExec;

ASSERT(!m_strQuery.IsEmpty());

if(m_pConnection == NULL)
m_pConnection = mpdb;

m_strQuery.TrimLeft();
BOOL bIsSelect = m_strQuery.Mid(0, _tcslen(_T("Select "))).CompareNoCase(_T("select ")) == 0 && nOption == openUnknown;

int maxRetries = 10;
bool bContinue = true;

CursorTypeEnum adCursorType = adOpenStatic;
if (!m_bSQLEngine)
{
// MDB Engine
adCursorType = adOpenStatic;
m_pConnection->CursorLocation = adUseClient;
}
else
{
// SQL Engine
adCursorType = adOpenDynamic;
m_pConnection->CursorLocation = adUseServer;
}

int currentCommandTimeout = m_pConnection->CommandTimeout;

if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();

for (int iRetry = 0; (iRetry < maxRetries) && bContinue; iRetry++)
{
try
{
// we just use an auto lock object so it is unlocked automatically, it uses same
// critical section object.
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();

int newCommandTimeout = currentCommandTimeout + 15 * iRetry;
m_pConnection->CommandTimeout = newCommandTimeout;


if(bIsSelect || nOption == openQuery || nOption == openUnknown)
{

m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adCursorType, adLockOptimistic, adCmdUnknown);
}
else if(nOption == openTable)
{
m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adOpenDynamic, adLockOptimistic, adCmdTable);
}
else if(nOption == openStoredProc)
{
m_pCmd->ActiveConnection = mpdb;
m_pCmd->CommandText = _bstr_t(m_strQuery);
m_pCmd->CommandType = adCmdStoredProc;

m_pRecordset = m_pCmd->Execute(NULL, NULL, adCmdText);
}
else
{
TRACE( _T("Unknown parameter. %d"), nOption);

if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();

return FALSE;
}

if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();

bContinue = false;
}
catch(_com_error &e)
{
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();

dump_com_error_without_exception(e, _T("Open"));

// retry Query timeout

CString szDescription;
_bstr_t bstrDescription(e.Description());
szDescription.Format( _T("%s"), (LPCTSTR)bstrDescription);

if ((szDescription.Find(_T("Query timeout expired")) == -1) || (iRetry == maxRetries - 1))
{
m_pConnection->CommandTimeout = currentCommandTimeout;
throw CADOException(e.Error(), e.Description());
}
Sleep (1000);
bContinue = true;
}

}

m_pConnection->CommandTimeout = currentCommandTimeout;

return m_pRecordset != NULL && m_pRecordset->GetState()!= adStateClosed;
}

为了完整起见,上面调用了这个函数:

static CCriticalSection* GetDbCriticalSection(const CString& database)
{
// For now we only care about one database and its corresponding critical section
if (database.CompareNoCase( _T("Alr") ) == 0)
return &g_csAlrDb; // g_csAlrDb is defined static global in this file
else
return 0;

}

Open() 函数被各种数据库调用,我只锁定保护对一个数据库的访问。正如您所看到的,有相应的锁定/解锁,因此不确定这些函数的代码如何使关键部分处于锁定状态。难道是因为MFC issue

最佳答案

就我而言,大多数情况下,当 C++ 软件在调试版本和发布版本之间表现不同时,这是因为未初始化的变量、链接的不同库或编译器优化适得其反。

要跟踪错误,请尝试评估变量和函数返回值,即 LoadString,例如使用 AfxMessageBox()

关于c++ - 代码在 WinDbg 上运行良好,但没有它就很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44790735/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com