Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Диплом Voldem@r / Оно / ПЗ_release.doc
Скачиваний:
48
Добавлен:
16.04.2013
Размер:
1.6 Mб
Скачать

2.2.2. Встроенные средства языка для отладки программ

Язык программирования Visual C++ 6.0 содержит специальные средства отладки [8]. дополняющие собой инструментальные средства отладки среды. Остановлюсь на некоторых из них, которые применялись при отладке разработанного программного комплекса.

Отладочные макросы

  • ASSERTиспользуется для проверки логических условий, которые должны выполняться в данной точке программы. Например, в функцию передаётся указатель и предполагается, что он всегда будет иметь ненулевое значение. Однако для предотвращения возможных ошибок это следует проверить. С этой целью перед использованием данного указателя следует вызвать макрос ASSERT: ASSERT (pObject) Всякий раз, когда логическое выражение, переданное в качестве аргумента макросу ASSERT, будет принимать значение FALSE, выполнение приложения будет останавливаться и на экран будет выводиться окно с сообщением об ошибке. После этого можно перейти в текст программы для отладки.

  • TRACE служит для вывода диагностических сообщений. Обычно заранее известны потенциальные места возникновения ошибок. Например, многие функции возвращают своим значением коды ошибок (в том числе и код такой специфической «ошибки», как успешное завершение). Эти коды возврата можно игнорировать, а можно и вывести их значения, чтобы была возможность проанлизировать выполнение программы. Именно для этих целей и применяется макрос TRACE.

Эти макросы выполняются только в отладочной версии программы. В окончательной версии (т.н. release), в которой не определена константа _DEBUG, данные макросы не выполняют никаких действий. Это позволяет оставлять их в тексте программы без опасения, что они замедлят выполнение окончательной версии приложения или будут выдавать непонятные сообщения конечному пользователю.

OutputDebugString() и отладочная консоль

В некоторых случаях для того, чтобы посмотреть значения переменных, не желательно или невозможно прерывать выполнение программы. Например, для многонитевого приложения или для участков кода, критичных ко времени выполнения. Более того, зачастую отладочная и окончательная версия программы ведут себя по-разному. И даже если отладочная версия работает без ошибок, то в окончательной версии они могут появиться. И здесь уже не воспользуешься отладчиком.

Для вывода какой-либо информации из приложения в этих случаях используется функцию OutputDebugString(), которая пишет в отладочную консоль – специальную консольную утилиту, содержащуюся в Visual Studio C++ 6.0 SDK (dbmon.exe). Эта функция принимает в качестве аргумента строку, которую и выводит в отладочную консоль. Применяя эту функцию в окончательной версии программы, можно локализовать местоположение ошибки последовательным приближением. На рис.2.7 показано использование отладочной консоли при отладке графического редактора в окончательной версии программы.

Рис 2.7 Пример отладки с использованием отладочной консоли

2.2.3. Отладка программного кода, содержащего stl и mfc

Так как библиотеки STL и MFC уже давно разработаны и отлажены, число ошибок в этих библиотеках минимально. Поэтому все ошибки в программах, использующих эти библиотеки, заключаются в неправильном использовании классов из этих библиотек.

Серьёзная проблема, с которой постоянно сталкиваются программисты – утечка памяти. Эта проблема может возникнуть в любом приложении. не обязательно в том. которое использует библиотеки STL или MFC. Однако использование специальных классов MFC даёт возможность локализовать место, в котором происходит неконтролируемая утечка памяти. Речь идёт о классе CMemoryState. Это класс обладает рядом методов, которые позволяют зафиксировать количество занятой памяти в любой момент времени, вычислить разницу в занимаемой памяти между двумя контрольными точками и вывести дамп памяти в окно отладки.

С отладкой кода с использованием библиотеки STL дела в Visual Studio C++ обстоят не так хорошо. Эта среда не имеет специальных средств для отладки такого кода. Например, окно Quick Watch не поможет, если необходимо просмотреть все элементы какого-нибудь контейнера, скажем, list. Для этого придётся вставлять в код отладочный цикл, в котором последовательно выбираются элементы из контейнера с помощью итератора. Код ниже иллюстрирует этот подход:

std::list<int> myList;

std::list<int>::iterator it;

for (it = myList.begin(); it != myList.end(); it++)

{

// теперь можно посмотреть значение текущего элемента с помощью *it

}

Тонким моментом при использовании библиотеки STL является применение контейнеров указателей. Дело в том, что при удалении указателя из контейнера, память, динамически выделенная для этого указателя, автоматически не освобождается. Поэтому следует быть особенно внимательным при работе с такими контейнерами, особенно если они создаются на стеке. Для обнаружения утечек памяти как раз подойдёт класс библиотеки MFC CMemoryState, описанный выше.

Типичной ошибкой при использовании классов STL является выход за границы. Следующий фрагмент кода иллюстрирует подобную ситуацию:

std::vector<double> myVector;

myVector.push_back(rand() / RAND_MAX);

int iPos;

cin >> iPos;

cout << myVector[iPos];

В случае, если значение переменной iPos будет отличным от 0, myVector[iPos] вернёт совершённо неожиданное значение. Найти такую ошибку не очень-то и просто. Для уменьшения вероятности появления ошибок подобного рода можно воспользоваться следующими рекомендациями. Во-первых, переменную iPos следует объявлять, как беззнаковое целое. А во-вторых, перед обращением к какому-либо элементу контейнера сравнить значение индекса и количество элементов в контейнере. Для получения количества элементов нужно вызвать функцию size(), которая присутствует в интерфейсе всех контейнеров библиотеки STL.

Соседние файлы в папке Оно