Призрачный сбой приложения при добавлении одного вызова функции - PullRequest
0 голосов
/ 03 июня 2011

Мое приложение имеет некоторый код отладки, написанный специально для отправки данных отладки в окно вывода при работе в режиме отладки.Когда в приведенном ниже фрагменте кода вызывается функция GetCurrTime, происходит сбой приложения при следующем вызове 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;
}

Просто для удовольствия, вот функция, в которую входит ПК, когда происходит сбой (оператор возврата последней строки функции):

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, которые он загрузил.

Это также может быть связано с тем, что пользователь нажимает F12, когда ZCT.exe находится в фокусе.

В окне вывода может быть больше диагностической информации.Программа '[0x9F4] ZCT.exe: Native' вышла с кодом 0 (0x0).

Есть идеи?

1 Ответ

2 голосов
/ 03 июня 2011
ptRetVal = (TCHAR *)::malloc( iTimeStrLen )

Будет выделять количество байтов, когда вы, вероятно, захотите выделить это число wchar_t s.

...