Анимация
JavaScript
|
Главная Библионтека интервале может произойти все что угодно. Если не использовать безопасную версию STL, обычно дело кончается нарушением защиты памяти с неприятными побочными эффектами и даже сбоем программы. В некотором смысле применение библиотеки STL так же чревато ошибками, как применение указателей в языке С. Найти такие ошибки иногда бывает очень трудно, особенно если нет безопасной версии STL. В частности, для нормальной работы STL должны выполняться перечисленные ниже условия. О Действительность итераторов. Например, перед использованием итераторы должны инициализироваться. Следует помнить, что итераторы могут стать недействительными вследствие побочных эффектов других операций. В частности, в векторах и деках это может произойти при вставке, удалении или перемещении элементов. О Конечный итератор не связан с элементом контейнера, поэтому вызов операторов * и -> для него недопустим. В частности, это относится к возврангае-мым значениям функций end() и rend() контейнерных классов. О Действительность интервалов: □ итераторы, определяющие интервал, должны огносигься к одному контейнеру; □ второй итератор должен быть достижим в результате перебора элементов, начиная от первого. О При использовании нескольких иттгервалов-источников второй и последующие интервалы должны содержать не меньше элементов, чем первый интервал. О Количество элементов в приемном интервале должно быть достаточным для перезаписи; в противном случае необходимо использовать итераторы вставки. Некоторые распространенные ошибки продемонстрированы в следующем примере: stl/iterbugl.cpp #1nclude <iostreani> #include <vector> #include <algorithm> using namespace std: int mainO { vector<int> colli: Пустая коллекция vector<int> col 12: Пустая коллекция /* ОШИБКА; * - начало находится за концом интервала vector<int>;;iterator pos = colU.beginO; reverse C++pos. colli.endO): Вставка эленентов со значениями от 1 до 9 в со112 for (int i=l; 1<=9; ++i) { con2.push back (1): /* ОШИБКА: * - перезапись несуществующих элементов сору {со112.beginO. соП2.епб{), Источник coin.beginO): Приемник /* ОШИБКА: * - перепутаны коллекции . * - перепутаны beg1n{) и endC) сору {colli.beginO. coll2.end{). Источник colli.endO): Приемник Все указанные ошибки происходят не на стадии компиляции, а do время вы-полнспия программы, поэтому оии приводят к непредсказуемым последствиям. Библиотека STL предоставляет массу возможностей для ошпбок. Она вовсе ие обязана защищать вас от самого себя, поэтому желательно (по крайней мере, на время разработки программы) использовать безопасную версию STL. Первая безопасная версия STL была разработана Кеем Хорстманом (Сау Horstmann). К сожалению, многие поставщики предоставляют версию STL, основанную на исходном варианте кода, в котором обработка ошибок не предусмотрена. Впрочем, с>1туация постепенно улучшается. Современная безопасная версия STL распространяется бесплатно практически для всех платформ (http: www.stlport.org/). Обработка исключений Проверка логических ошибок в STL практически отсутствует, поэто.му сама библиотека STL почти не генерирует исключения, связанные с логикой. Фактически существует только одна функция, для которой в стандарте прямо указано на возможность возникновения исключения: речь идет о функции at() векторов и деков (проверяемой версии оператора индексирования). Во всех остальных случаях стандарт требует лишь стандартных исключений типа bad alioc при нехватке памяти или исключений, возникающих при пользовательских операциях. Когда генерируются исключения и что при этом происходит с компонентами STL? В течение долгого времени, пока шел процесс стандартизации, строгих правил на этот счет не существовало. В сущности, любое исключение приводило к непредсказуемым последствиям. Даже уничтожение котхтейнера STL после того, как во время выполнения одной из поддерживаемых им операций произошло исключение, тоже приводило к непредсказуемым последствиям (например, аварийному завершению программы). Из-за этого библиотека STL оказывалась бесполезной там, где требовалось гарантированное четко определенное поведение, потому что не была предусмотрена даже возможность раскрутки стека. За безопасной версией STL Кея Хорстмана обращайтесь по адресу http: www.horstmann. com/safestl.html. Обработка исключений стала одним из последних вопросов, обсуждавшихся в процессе стандартизации. Найти хорошее решение оказалось нелегко. На это понадобилось много времени, что объяснялось двумя основными причинами. О Было очень трудно определить, какую степень безопасности должна обеспечивать стандартная библиотека С++. Напрашивается мысль, что всегда следует обеспечивать максимальный уровень из всех возможных. Например, можно потребовать, чтобы вставка нового элемента в произвольной позиции вектора либо завершалась успешно, либо не вносила изменений. Однако исключение может произойти в процессе копирования элементов, расположенных после позиции вставки, на следующую позицию для освобождения места под новый элемент; в этом случае полное восстановление невозможно. Чтобы добиться указанной цели, вставку пришлось бы реализовать с копированием всех элементов вектора в новую область памяти, что серьезно отразилось бы на быстродействии. Если приоритетной задачей проектирования является высокое быстродействие (как в случае STL), обеспечить идеальную обработку исключений для всех возможных ситуаций все равно не удастся. Приходится искать компромисс между безопасностью и скоростью работы. О Многие беспокоились о том, что присутствие кода обработки исключений отрицательно скажется на быстродействии. Это противоречило бы главной цели проектирования - обеспечению максимального быстродействия. Впрочем, разработчики компиляторов утверждают, что в принципе обработка исключений реализуется без сколько-нибудь заметного снижения быстродействия (причем такие реализации уже существуют). Несомненно, лучше иметь гарантированные четко определенные правила обработки исключений без заметного снижения быстродействрш, чем рисковать системными сбоями из-за исключений. В результате этих обсуждений стандартная библиотека С++ теперь предоставляет базовую гарантию безопасности исключений: возникновение исключений в стандартной библиотеке С++ не приводит к утечке ресурсов или нарушению контейнерных инвариантов. К сожалению, во многих случаях этого недостаточно. Довольно часто требуется более твердая гарантия того, что при возникновении исключения произойдет возврат к состоянию, имевшему место перед началом операции. О таких операциях говорят как об атомарных по отношению к исключениям, а если воспользоваться терминологаей баз данных, можно сказать, что эти операции должны обеспечивать возможность либо принятия, либо отката, то есть тратакционную безопасность. В том, что касается этих требований, стандартная биб.нютека С++ теперь гарантирует две вещи. О Для всех узловых контейнеров (списки, множества, мультимножества, отображения и мультиотображения) неудачная попытка создания узла просто оставляет контейнер в прежнем состоянии. Более того, удаление узла не может завершиться неудачей (если исключение не произойдет в деструкгоре). Однако при вставке нескольких элементов в ассоциативный контейнер из-за необходимости сохранения порядка сортировки обеспечивать полное восстанов.;1ение Спасибо Дейву Абрахамсу (Dave Abrahams) и Грегу Колвипу (Greg Colviu) за их работу в области безопасности исключений в стандарте С++, а также за информацию, полученную от HVIX ни этой теме. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 [ 43 ] 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |