Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
В Windows предусмотрен еще один способ получить информацию от программы во время ее исполнения – функция OutputDebugString. Функция принимает LPCTSTR-строку и посылает ее отладчику, под управлением которого исполняется приложение. В случае запуска приложения из Visual C++ посланная строка попадает в окно Output последнего (закладка Debug). Преимущество данного способа в том, что он не требует прерывать работу программы для отслеживания значений (что иногда критично – например, при отлаживании обработчика сообщения WWM_TIMER или асинхронного выполнения функций), и не требует убирать лишний код после отлаживания нужного участка (в отличие, скажем, от метода с MessageBox).
OutputDebugString можно использовать следующим образом:
void CPerson::SetPersonAge(int nAge) {
ASSERT((nAge>=0) && (nAge<200));
m_nAge = x;
CString str;
str.Format(_T("New age = %d\n"), nAge);
OutputDebugString(str);
}
MFC упрощает вывод отладочной информации, определяя глобальный объект afxDump класса CDumpContext. Информация при этом выводится таким образом:
void CPerson::SetPersonAge(int nAge) {
ASSERT((nAge>=0) && (nAge<200));
m_nAge = x;
afxDump << _T("New age = ") << nAge << _T("\n");
}
Отладочную информацию можно также выводить макросами TRACE, TRACE0, TRACE1, TRACE2 и TRACE3 (для таких целей обычно их и используют). Все они выводят переданную им информацию через afxDump, при этом принимают те же параметры, что и функция printf:
void CPerson::SetPersonAge(int nAge) {
ASSERT((nAge>=0) && (nAge<200));
m_nAge = x;
TRACE(_T("New age = %d\n"), nAge);
}
Макросы TRACEn аналогичны макросу TRACE, с той лишь разницей, что их первый параметр имеет тип LPCSTR (а не LPCTSTR), и они принимают не произвольное число параметров, а определенное цифрой в их имени. Длина первого параметра всех TRACE-макросов (после всех подстановок) не должна превышать 512 символов, иначе макрос сгенерирует ASSERT.
Макросы TRACEn оставлены в MFC для обратной совместимости, при написании приложений рекомендуется пользоваться макросом TRACE.
ПРИМЕЧАНИЕ
Вывод отладочной информации и через afxDump, и через TRACE-макросы работает только в Debug-версии приложения.
В поставку Visual Studio 6.0 входит утилита для настройки вывода информации через TRACE-макросы – "MFC Tracer" (tracer.exe). С ее помощью можно отключить вывод отладочной информации (даже при Debug-сборке), заставить MFC выводить перед каждым сообщением в окне Output имя сгенерировавшего это сообщение проекта (полезно при отладке проекта, использующего DLL или состоящего из нескольких приложений), включить вывод уведомлений MFC об обработке определенных оконных сообщений и т.д.
Заканчивая обсуждение отладочной информации, нельзя не упомянуть утилиту TRACEWIN, написанную Paul DiLascia, также доступную в исходных текстах в апрельском номере MSJ за 1997 год. Эта утилита внедряется во все запускаемые процессы, и для MFC Debug-проектов перенаправляет весь TRACE-вывод в отдельное окно (причем перенаправление автоматически включается даже для уже запущенных приложений). Очень удобный инструмент. Более того, в той же статье Paul DiLascia доходчиво разъясняет принципы внедрения DLL в чужой процесс и приводит C++-класс, облегчающий эту задачу.
afxDump позволяет выводить в окне отладчика не только переменные, но и целые объекты (порожденные от CObject). Конструкция afxDump << &myPerson (или afxDump << myPerson ) развернется в вызов myPerson.Dump(afxDump) (виртуальная функция класса CObject). Разрабатывая собственный класс, программист может переопределить эту функцию, реализовав свой метод вывода внутренней информации объекта, например, вот так:
// CPerson унаследован от CObject
void CPerson::Dump(CDumpContext &dc) const {
CObject::Dump(dc);
dc << T("Age = ") << m_nAge;
}
Вызов родительской функции CObject::Dump(dc) выведет на контекст имя класса, в случае, если для реализации этого класса (CPerson в примере выше) используется связка макросов DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC (или DECLARE_SERIAL/IMPLEMENT_SERIAL). Обратите внимание, что посылка символа перевода строки в переопределенной Dump не требуется.
ПРИМЕЧАНИЕ
Вывод отладочной информации об объекте через функцию Dump будет работать только в Debug-версии приложения, но здесь разработчик должен сам позаботиться о выполнении этого ограничения – и объявление, и реализацию, и вызовы функции Dump следует обрамлять проверками на Debug-сборку проекта:
class CPerson : public CObject {
...
public:
#ifdef _DEBUG
void Dump(dc) const;
void AssertValid() const; // это же касается объявления AssertValid
// (но не использования макроса ASSERT_VALID!)
#endif
...
};
После выполнения всех этих действий остается только скинуть в afxDump указатель на наш объект, и изучать полученную информацию в Output-окне отладчика. Многие классы MFC реализуют функцию Dump для диагностики их внутреннего состояния, что особенно полезно при отладке работы с классами-коллекциями C*Array, C*List и C*Map. Чтобы получить и состояние объектов, содержащихся в коллекции, нужно установить глубину вызова Dump-функции, отличную от 0, функцией SetDepth(int newDepth) класса CDumpContext:
CArray arrPersons;
WorkWithArray(arrPersons); // здесь идет работа с массивом
#ifdef _DEBUG
afxDump.SetDepth(1); // вывести информацию не только о коллекции,
afxDump << &arrPersons; // но и о всех ее членах (будет вызвана
// CPerson::Dump для каждого элемента массива)
#endif
Одна из самых распространенных ошибок при работе с памятью – выделение блока памяти (к примеру, при создании нового объекта) без его последующего освобождения (так называемые утечки памяти). Сами по себе эти утечки нефатальны ни для работы приложения, ни для работы системы (по завершению работы приложения Windows все равно освободит все занятые приложением блоки памяти), но это может привести к нехватке памяти, если приложение исполняется относительно долгое время (например, если это WinNT-сервис). Обычно для отслеживания утечек памяти используют специализированные программы, например, NuMega BoundsChecker, но и в MFC предусмотрены некоторые возможности для диагностики подобных ситуаций.
Класс CMemoryState предназначен для обнаружения динамически выделенных и не освобожденных впоследствии блоков памяти. Алгоритм работы с этим классом сводится к запоминанию списка созданных объектов функцией CMemoryState::Checkpoint, и последующим сравнением двух классов функцией CMemoryState::Difference. Например, вот так:
#ifdef _DEBUG
CMemoryState msStart, msEnd, msDiff;
msStart.Checkpoint(); // начало подозрительного блока
#endif
...
CPerson *pPerson = new CPerson();
...
#ifdef _DEBUG
msEnd.Checkpoint(); // конец подозрительного блока
if (msDiff.Difference(msStart, msEnd) {
Интервал:
Закладка: