Безопасность по исключениям
Предварительное предупреждение: Надежность по исключениям - незавершенная возможность! Общие случаи будут работать, но классы могут допускать утечки памяти или даже фатальные сбои.
Сама Qt не генерирует исключения. Вместо этого используются коды ошибок. Кроме того, некоторые классы содержат выводимые пользователю сообщения об ошибках, например, QIODevice::errorString() или QSqlQuery::lastError(). Этому есть исторические и практические причины - включение исключений может увеличить размер библиотеки более чем на 20%.
В следующих разделах описывается поведение Qt если включена поддержка исключений во время компиляции.
Безопасные по исключениям модули
Контейнеры
Контейнерные классы Qt как правило нейтральны с точки зрения исключений. Они передают любое исключение, которое произойдет внутри содержащегося в них типа T, пользователю наряду с сохранением своего внутреннего состояния валидным.
Пример:
QList<QString> list;
...
try {
list.append("hello");
} catch (...) {
}
Исключениями в этом правиле являются контейнеры типов, которые могут генерировать исключения во время выполнения конструкций присваивания или копирования. Для этих типов функции, которые изменяют контейнер чтобы вернуть значение, являются небезопасными для использования:
MyType s = list.takeAt(2);
Если исключение произойдет во время присваивания s, значение с индексом 2 уже удалено из контейнера, но еще не присвоено s. Оно будет потеряно без шанса на восстановление.
Правильный способ записать это:
MyType s = list.at(2);
list.removeAt(2);
Если присваивание возбудит исключение, контейнер по-прежнему содержит значение, потери данных не произойдет.
Обратите внимание на то, что классы Qt с неявным разделением данных не будут возбуждать исключение в своих операторах присваивания или конструкторах копирования, поэтому вышеприведенное ограничение не применяется.
Обработка нехватки памяти
Большинство настольных операционных систем выделяют больше памяти, чем обладают физически. Это означает, что malloc() или оператор new возвращает действительный правильный указатель, даже несмотря на недостаток доступной памяти в момент её выделения. На таких системах исключения типа std::bad_alloc не возбуждается.
На всех остальных операционных системах Qt возбудит исключение типа std::bad_alloc, если выделение закончилось неудачно. Выделение может закончиться неудачно, если система работает при нехватке памяти или не имеет достаточно непрерывной памяти чтобы выделить требуемый размер.
Исключения из этого правила документирования. Для примера, если памяти недостаточно, то QImage::create() возвратит false вместо возбуждения исключения.
Восстановление после исключений
В настоящее время единственный поддерживаемый случай использования для восстановления после возбуждения исключений внутри Qt (например, из-за нехватки памяти) - выход из цикла обработки событий и проведение некоторой уборки перед завершением работы приложения.
Типичный вариант использования:
QApplication app(argc, argv);
...
try {
app.exec();
} catch (const std::bad_alloc &) {
return 0;
}
После возбуждения исключения соединение с оконным сервером может быть уже закрыто. Это небезопасно для вызова функции, связанной с ГПИ, после того как поймано исключение.
Платформо-зависимая обработка исключений
Платформа Symbian
Платформа Symbian реализует свою собственную систему исключений, которая отличается от стандартного механизма C++. При использовании Qt для платформы Symbian и особенно при написании кода для непосредственного доступа к функциональности Symbian, необходимо знать о базовой реализации и о том, как она взаимодействует с Qt.
Документ Безопасность по исключениям с Symbian показывает, как использовать возможности, предоставленные Qt, для использования исключение настолько безопасно, насколько возможно.
| Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) |
Торговые марки |
Qt 4.6.4 |
|