添加一个函数调用时应用程序幻象崩溃
Posted
技术标签:
【中文标题】添加一个函数调用时应用程序幻象崩溃【英文标题】:Application Phantom Crash When One Function Call Added 【发布时间】:2011-06-03 15:50:58 【问题描述】:我的应用程序有一些专门编写的调试代码,用于在调试模式下运行时将调试数据发送到输出窗口。当在下面的代码 sn-p 中调用函数 GetCurrTime
时,当我单步执行代码时,应用程序会在以下对 malloc
的调用中崩溃,或者在调用 malloc
之前的行(如果我让它释放) -跑。然而,真正奇怪的是,当崩溃发生时,PC 并没有落在这两条线上。 PC 在完全不相关的功能中停止在返回线上。它变得更好了。调用堆栈没有显示函数返回的位置。我猜这台电脑不知何故陷入了困境。让这一切变得非常奇怪的是,当我注释掉对 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;
这是输出窗口中打印的错误:
0x7c936822 处的第一次机会异常 在 ZCT.exe 中:0xC0000005:访问 违规读取位置 0x00000000。 HEAP[ZCT.exe]:堆缺少最后一个条目 在 5451460 附近的承诺范围内 Windows 触发了一个断点 ZCT.exe。
这可能是由于 堆,表示 ZCT.exe 中的错误 或它已加载的任何 DLL。
这也可能是由于用户 在 ZCT.exe 获得焦点时按 F12。
输出窗口可能有更多 诊断信息。该程序 '[0x9F4] ZCT.exe: Native' 已退出 代码为 0 (0x0)。
有什么想法吗?
【问题讨论】:
为ptTimeStr
(也可能为pCmdIdStr
)分配的内存永远不会被释放,所以这里有内存泄漏。我认为 Bo 在下面的回答是您当前问题的来源。
【参考方案1】:
ptRetVal = (TCHAR *)::malloc( iTimeStrLen )
当您可能想要分配该数量的wchar_t
s 时,将分配该数量的字节。
【讨论】:
ptRetVal = (TCHAR *)::malloc( iTimeStrLen * sizeof(TCHAR) ) 我不确定您是否不需要在末尾为空字符添加 +1字符串 malloc( (iTimeStrLen + 1) * sizeof(TCHAR) )以上是关于添加一个函数调用时应用程序幻象崩溃的主要内容,如果未能解决你的问题,请参考以下文章
dataSnapshot 函数不起作用 - 函数调用时应用程序崩溃
从不同的 VC 访问时,带有完成处理程序的 API 调用函数崩溃