Программирование >>  Разработка устойчивых систем 

1 ... 19 20 21 [ 22 ] 23 24 25 ... 196


присзггствует ли заданный указатель в карте памяти. Если указатель не найден, значит, вы пытаетесь освободить блок, либо отсутствующий в куче, либо уже освобожденный ранее и удаленный из кучи. Переменная activePlag ифает важную роль, потому что мы не хотим обрабатывать операции освобождения памяти, обусловленные завершением работы системы. При вызове MEM OFF() в конце программы флаг activeFlag становится равным false, и последующие вызовы delete игнорируются (конечно, в обычной программе так делать нельзя, но мы занимаемся поиском утечки памяти в вашем коде, а не отладкой библиотеки). Простоты ради, вся работа версий операторов new и delete для массивов перепоручается их скалярным аналогам.

Ниже приведен простой тест, в котором используется система MemCheck:

: C02:MemTest.cpp {L} MemCheck Test of MemCheck system #1nclude <iostream> #include <vector> #include <cstr1ng>

#include MemCheck.h Должен включаться последним! using namespace std: class Foo { char* s: public: Foo(const char*s ) ( this->s = new char[strlen(s) + 1]: strcpy(this->s. s):

-FooO { delete [] s:

int mainO { MEM ON():

cout hello\n : int* p = new int: delete p;

int* q = new int[3]: delete [] q: int* r: delete r: vector<int> v: v.push back(l): Foo s( goodbye ): MEM OFF(): } III:-

Этот пример доказывает, что система MemCheck может использоваться с потоками, стандартными контейнерами и классами, выделяющими память в конструкторах. Память по указателям р и q выделяется и освобождается без проблем, но г не является действительным указателем на память в куче, поэтому в выходных данных включается сообщение об ошибке освобождения неизвестного указателя:

hello

Allocated 4 bytes at address 0xa010778 (file: memtest.cpp. line: 25) Deleted memory at address 0xa010778

Allocated 12 bytes at address 0xa010778 (file: memtest.cpp. line: 27) Deleted memory at address 0xa010778 Attempt to delete unknown pointer: 0x1

Allocated 8 bytes at address Oxa0108cO (file: memtest.cpp. line: 14)



Итоги

Тщательное предварительное планирование помогает решить многие проблемы, возникающие при программировании. Даже те программисты, которые не привыкли постоянно пользоваться макросом assert(), все равно применяют некие воображаемые аналоги утверждений в своих циклах и функциях. Макрос assert() упрощает поиск ошибок, а программы становятся более понятными. Однако следует помнить, что утверждения должны применяться только для проверки инвариантов, но не для обработки ошибок времени выполнения.

Ничто не вселяет в программиста такое спокойствие духа, как тщательно протестированная программа. Если раньше тестирование казалось вам мучительной и неприятной процедурой, воспользуйтесь средствами автоматизации, наподобие представленных в этой главе, и сделайте его частью своей повседневной работы. Это пойдет на пользу - как вам, так и пользователям ваших программ!

Упражнения

1. Напишите тестовую программу, использующую систему TestSuite, для стандартного класса vector. Программа должна проверять работу следующих функций целочисленного вектора: push back() (присоединяет элемент в конец вектора), front() (возвращает первый элемент вектора), Ьаск() (возвращает последний элемент вектора), рор Ьаск() (удаляет последний элемент, не возвращая его), at() (возвращает элемент с заданным индексом) и size() (возвращает количество элементов). Убедитесь в том, что для недопустимых индексов функция vector::at() генерирует исключение std::out of range.

2. Предположим, вы разрабатываете класс Rational для представления рациональных чисел (дробей). Объекты Rational всегда хранятся в нормализованном виде, а нулевой знаменатель является ошибкой. Примерный интерфейс класса Rational выглядит так:

: C02:Rational.h {-хо} #ifndef RATIONAL H #define RATIONALJ #include <iosfwd>

class Rational { public:

Rational(int numerator =0. int denominator =1): Rational operator-O const:

Deleted memory at address ОхаОЮбсО No user memory leaks!

Из-за вызова MEM OFF() последующие вызовы функций operator delete() из объектов vector и ostream не обрабатываются. Теоретически еще возможны отдельные вызовы delete из-за перераспределений памяти, выполненных контейнерами.

Если вызвать TRACE OFF() в начале программы, результат будет таким:

hello

Attempt to delete unknown pointer: 0x1 No user memory leaks!



friend Rational operator+(const Rationa1&.

const RationalS) friend Rational operator-(const Rational&.

const Rational&) friend Rational operator*(const RationalS.

const Rational&> friend Rational operator/(const Rational&.

const Rational): friend ostreamS operator (ostream&.

const Rational): friend istreamS operator (istreams. RationalS). RationalS operator+=(const RationalS): RationalS operator-=(const RationalS): RationalS operator*=(const RationalS): RationalS operator/=(const RationalS): friend bool operator<(const RationalS.

const Rationale): friend bool operator>(const RationalS.

const RationalS); friend bool operator<=(const RationalS.

const RationalS); friend bool operator>=(const Rati oral&, const RatioiialS): fnend bool operator-=(const RationalS, const RationalS): friend bool operator!=(const RationalS.

const Rational&); }:

#endif RATIONAL H /:-

Напишите полную спецификацию этого гсласса с предусловиями, постусловиями и спецификациями исключений.

3. Напишите тест с использованием системы TestSuite, который бы досконально тестировал спецификации из предыдущего примера (в том числе и исключения).

4. Реализуйте luiacc Rational так, чтобы все тесты из предыдущего упражнения завершались успешно. Используйте утверждения только для инвариантов.

5. Приведенный ниже файл BuggedSearch.cpp содержит функцию бинарного поиска what в интервале [beg,end). Алгоритм содержит ряд ошибок. Отладьте функцию поиска при помощи средств трассировки, описанных в этой главе.

С02:BuggedSearch.cpp {-хо} {L} ../TestSuite/Test #include ../TestSuite/Test.h #include <cstdlib> #include <ctime> #include <cassert> #include <fstream> using namespace std:

Функция содержит ошибки

int* binarySearch(int* beg. int* end. int what) { while(end - beg != 1) { if(*beg == what) return beg: int mid = (end - beg) / 2: if(what <= beg[mid]) end = beg + mid: else beg = beg + mid:



1 ... 19 20 21 [ 22 ] 23 24 25 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика