私のアプリケーションには、デバッグモードで実行しているときにデバッグデータを出力ウィンドウに送信するために特別に記述されたデバッグコードがあります。以下のコードスニペットで関数が呼び出されると、コードをステップ実行するときの次の呼び出しで、またはフリーランさせた場合は、の呼び出しの前の行GetCurrTime
でアプリケーションがクラッシュします。ただし、ここでの本当の奇妙な点は、クラッシュが発生したときに、PCがこれらの回線のいずれにも着陸しないことです。PCは、まったく関係のない機能でリターンラインで停止します。それは良くなります。コールスタックは、関数が戻る場所を示していません。どういうわけかPCが雑草の中に入っていると思います。これを本当に奇妙なものにしているのは、私がコメントアウトすると、問題への呼びかけがなくなるということです。malloc
malloc
GetCurrTime
void PrintDevMsgTrace( LPBYTE pMsg, PWCHAR fnName )
{
#ifdef _DEBUG
BYTE byMsgLen;
TCHAR * ptTimeStr = NULL;
WORD cmd;
int i, j = 0;
int iTimeStrLen, iStrLen, iPreOffset, iPostOffset;
wchar_t * pCmdIdStr = NULL;
wchar_t * pBuf = NULL;
byMsgLen = pMsg[DEV_LEN_OFFSET] + sizeof(devPktHead_t) + sizeof(devPktTail_t);
cmd = pMsg[DEV_CMD_MSB_OFFSET];
cmd <<= 8;
cmd |= pMsg[DEV_CMD_LSB_OFFSET];
pCmdIdStr = GetCmdIdStr( cmd );
ptTimeStr = GetCurrTime();
iTimeStrLen = ::wcsnlen_s( ptTimeStr, 128 );
iPreOffset =
iTimeStrLen // time string
+ 1 // "-"
+ ::wcsnlen_s( fnName, 128 ) // function name
+ 3 // " : "
+ ::wcsnlen_s( pCmdIdStr, 128 ) // command ID string
+ 3; // " 0x"
iPostOffset = iPreOffset + byMsgLen * 3; // "%.2X " (formatted: 2 hex-nibble bytes and space)
iStrLen = iPostOffset + 3; // "\r\n\0"
pBuf = (wchar_t *)::malloc( iStrLen * sizeof(wchar_t) );
::swprintf_s( pBuf, iStrLen, _T("%s-%s : %s 0x"), ptTimeStr, fnName, pCmdIdStr);
for ( i = iPreOffset; i < iPostOffset; i += 3 )
{
::swprintf_s( &(pBuf[i]), 4, _T("%.2X "), pMsg[j++] );
}
::swprintf_s( &(pBuf[i]), 3, _T("\r\n") );
TRACE(pBuf);
::free( pBuf );
#endif
}
TCHAR * GetCurrTime( void )
{
DWORD dwError = ERROR_SUCCESS;
TCHAR * ptRetVal = NULL;
#ifdef _DEBUG
int iTimeStrLen;
do
{
if ( (iTimeStrLen = ::GetTimeFormat( LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, NULL, 0 )) == 0 )
{
dwError = ::GetLastError();
TRACE(_T("%s : Failed getting time format.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), _T(__FUNCTION__), dwError, _T(__FILE__), __LINE__);
continue;
}
if ( (ptRetVal = (TCHAR *)::malloc( iTimeStrLen )) == NULL )
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
TRACE(_T("%s : Not enough memory.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), _T(__FUNCTION__), dwError, _T(__FILE__), __LINE__);
continue;
}
if ( ::GetTimeFormat( LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, ptRetVal, iTimeStrLen ) == 0 )
{
dwError = ::GetLastError();
TRACE(_T("%s : Failed getting time format.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), _T(__FUNCTION__), dwError, _T(__FILE__), __LINE__);
continue;
}
}
while ( 0 );
#endif
if ( dwError != ERROR_SUCCESS )
{
::free( ptRetVal );
ptRetVal = NULL;
}
::SetLastError( dwError );
return ptRetVal;
}
キックのためだけに、クラッシュが発生したときにPCが到達する関数は次のとおりです(関数の最後の行のreturnステートメント)。
LPVOID CLinkList::Add( LPVOID pItem, DWORD len )
{
DWORD dwError = ERROR_SUCCESS;
LPVOID pItemCopy = NULL;
LPLIST_NODE_T ptNode = NULL;
do
{
// Validate parameters.
if ( (pItem == NULL) || (len == 0) )
{
dwError = ERROR_INVALID_PARAMETER;
TRACE(_T("CLinkList::Add : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
continue;
}
if ( this->m_blCopy == FALSE )
{
pItemCopy = pItem;
}
else if ( (pItemCopy = ::malloc( len )) == NULL )
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
TRACE(_T("CLinkList::Add : Failed to allocate memory.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
continue;
}
else
{
::memcpy( pItemCopy, pItem, len );
}
if ( (ptNode = (LPLIST_NODE_T)::malloc( sizeof(LIST_NODE_T) )) == NULL )
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
TRACE(_T("CLinkList::Add : Failed to allocate memory.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
continue;
}
ptNode->next = NULL;
ptNode->item = pItemCopy;
ptNode->len = len;
if ( this->m_ptFirstNode == NULL )
{
ptNode->prev = NULL;
this->m_ptFirstNode = ptNode;
}
else
{
ASSERT(this->m_ptLastNode != NULL);
ptNode->prev = this->m_ptLastNode;
this->m_ptLastNode->next = ptNode;
}
this->m_ptLastNode = ptNode;
this->m_dwItemCount++;
}
while ( 0 );
if ( dwError != ERROR_SUCCESS )
{
::free( ptNode );
if ( this->m_blCopy != FALSE )
{
::free( pItemCopy );
}
pItemCopy = NULL;
}
::SetLastError( dwError );
return pItemCopy;
}
これは、出力ウィンドウに出力されるエラーです。
ZCT.exeの0x7c936822でのファーストチャンス例外:0xC0000005:アクセス違反の読み取り場所0x00000000。HEAP [ZCT.exe]:5451460付近のコミットされた範囲の最後のエントリがヒープにありませんWindowsがZCT.exeのブレークポイントをトリガーしました。
これは、ヒープの破損が原因である可能性があります。これは、ZCT.exeまたはロードされたDLLのいずれかにバグがあることを示しています。
これは、ZCT.exeにフォーカスがあるときにユーザーがF12キーを押したことが原因である可能性もあります。
出力ウィンドウには、より多くの診断情報が表示される場合があります。プログラム'[0x9F4]ZCT.exe:Native'がコード0(0x0)で終了しました。
何か案は?