Application Phantom Crash When One Function Call Added
My application has some debug code written specifically to send debug data to the Output Window when running in debug mode. When the function GetCurrTime
is called in the below code snippet the application crashes on the following call to malloc
when I step through the code, or on the line preceding the call to malloc
, if I let it free-run. However, the real oddity here is that when the crash occurs, the PC does not land on either of these lines. The PC stops on the return line in an entirely unrelated function. It gets better. The Call Stack shows no place for the function to return to. I'm guessing that somehow the PC is getting off into the weeds. What makes this all really odd, is that when I comment out the call to GetCurrTime
the problem goe开发者_运维问答s away.
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;
}
Just for kicks, here's the function the PC lands in when the crash occurs (on the return statement of the last line of the function):
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;
}
This is the error, as printed in the Output Window:
First-chance exception at 0x7c936822 in ZCT.exe: 0xC0000005: Access violation reading location 0x00000000. HEAP[ZCT.exe]: Heap missing last entry in committed range near 5451460 Windows has triggered a breakpoint in ZCT.exe.
This may be due to a corruption of the heap, which indicates a bug in ZCT.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while ZCT.exe has focus.
The output window may have more diagnostic information. The program '[0x9F4] ZCT.exe: Native' has exited with code 0 (0x0).
Any ideas?
ptRetVal = (TCHAR *)::malloc( iTimeStrLen )
Will allocate a number of bytes when you probably want to allocate that number of wchar_t
s.
精彩评论