Поделиться через


Отслеживание запросов выделения кучи

Обновлен: Ноябрь 2007

Этот раздел применим к:

Выпуск

Visual Basic

C#

C++

Web Developer

Экспресс-выпуск

Тема не применяется Тема не применяется

Только машинные коды

Тема не применяется

Standard

Тема не применяется Тема не применяется

Только машинные коды

Тема не применяется

Pro и Team

Тема не применяется Тема не применяется

Только машинные коды

Тема не применяется

Обозначения:

Тема применяется

Применяется

Тема не применяется

Неприменимо

Тема применяется, но команда по умолчанию сокрыта

Команда или команды скрытые по умолчанию.

Хотя точное указание имени исходного файла и номера строки, на которой стоит утверждение или выполняется макрос, часто очень полезно для выявления причины проблемы, этого не всегда достаточно для функций выделения кучи. Поскольку макросы могут вставляться в разные места логического дерева приложения, выделение часто скрыто в специальной программе из библиотеки DLL, которая тоже может вызываться из разных мест и в разное время. И поэтому вопрос обычно не в том, какая строка кода осуществила некорректное выделение, а в том, которое из тысяч выделений, сделанных этой строкой, было некорректным и почему.

Уникальные номера запросов выделения и _crtBreakAlloc

Наиболее простой способ идентифицировать запрос на указанное выделение кучи, ставшее некорректным, — воспользоваться преимуществом уникального номера запроса выделения, связанного с каждым блоком в отладочной куче. Когда данные о блоке помещены в отчет одной из функций дампа, этот номер запроса выделения заключается в фигурные скобки (например, "{36}").

Узнав номер запроса выделения некорректно выделенного блока, можно его передать в _CrtSetBreakAlloc и создать точку останова. Перед выделением блока выполнение прервется, и можно вернуться и определить, какая процедура отвечает за плохой вызов. Во избежание перекомпиляции эти же действия можно проделать в отладчике, присвоив _crtBreakAlloc номер запроса интересующего выделения.

Создание отладочных версий процедур выделения

Несколько более сложный подход — создание отладочных версий собственных процедур выделения, сопоставимых с версиями _dbgфункций выделения кучи. Можно передать аргументы исходного файла и номера строки базовым процедурам выделения кучи и сразу же увидеть, где возникло проблемное выделение.

Например, допустим, что приложение содержит обычную процедуру, наподобие следующей:

int addNewRecord(struct RecStruct * prevRecord,
                 int recType, int recAccess)
{
    // ...code omitted through actual allocation... 
    if ((newRec = malloc(recSize)) == NULL)
    // ... rest of routine omitted too ... 
}

В файле заголовка можно добавить следующий код:

#ifdef _DEBUG
#define  addNewRecord(p, t, a) \
            addNewRecord(p, t, a, __FILE__, __LINE__)
#endif

Затем можно изменить выделение в процедуре создания записи следующим образом:

int addNewRecord(struct RecStruct *prevRecord,
                int recType, int recAccess
#ifdef _DEBUG
               , const char *srcFile, int srcLine
#endif
    )
{
    /* ... code omitted through actual allocation ... */
    if ((newRec = _malloc_dbg(recSize, _NORMAL_BLOCK,
            srcFile, scrLine)) == NULL)
    /* ... rest of routine omitted too ... */
}

Теперь имя исходного файла и номер строки, где вызывалась addNewRecord, будут сохранены в каждом выделенном в отладочной куче блоке и помещены в отчет при проверке этого блока.

См. также

Другие ресурсы

Куча отладки CRT