|
Программирование >> Разработка устойчивых систем
присзггствует ли заданный указатель в карте памяти. Если указатель не найден, значит, вы пытаетесь освободить блок, либо отсутствующий в куче, либо уже освобожденный ранее и удаленный из кучи. Переменная 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:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |