Начну с примера. Есть такая функция mid() для контейнерных классов, в частности для QVector. Она позволяет получить вырезку из середины контейнера. В описании функции значится следующее:
Returns a sub-vector which contains elements from this vector, starting at position pos. If length is -1 (the default), all elements after pos are included; otherwise length elements (or all remaining elements if there are less than length elements) are included.
Для длины указано одно специальное значение -1, так же сказано, что если length больше реального хвоста, то будут взяты все оставшиеся элементы. Что же произойдёт, если позиция будет отрицательной или превышающей реальный размер контейнера, а также при других отличных от -1 отрицательных значения длины - не понятно. Приходится лезть в исходники и смотреть самому:
QContainerImplHelper::CutResult QContainerImplHelper::mid(int originalLength, int *_position, int *_length)
{
int &position = *_position;
int &length = *_length;
if (position > originalLength)
return Null;
if (position < 0) {
if (length < 0 || length + position >= originalLength)
return Full;
if (length + position <= 0)
return Null;
length += position;
position = 0;
} else if (uint(length) > uint(originalLength - position)) {
length = originalLength - position;
}
if (position == 0 && length == originalLength)
return Full;
return length > 0 ? Subset : Empty;
}
Здесь уже обработаны все ситуации и поэтому реального выхода за границы массива, и как следствие UB, мы получить вроде бы не должны. Но почему же этого не указано в "верхнем" описании функции в справочном центре? Может быть предполагается, что для каких-то "особо оптимизированных" случаев этих проверок не будет? Или Qt это в первую очередь максимальная защита от дурака?
Пока же получается, что если человек приходит в мир Qt из чистого C++ он будет довешивать дополнительные проверки аргументов перед вызовом, дабы не словить UB, хотя эти проверки уже есть внутри библиотеки. Таким образом тратя время на ненужный код. А тот, кто наоборот, начинал с Qt при переходе в чистый C++ получит по полной программе всевозможных Access Violation в рантайме.
В итоге, хочется понять, чем же всё таки руководствоваться при разработке кода, используя библиотеку Qt. Можно ли полагаться на максимальную безопасность и проверку параметров всегда и везде или всё же кое-где стоит обеспечивать ручную проверку, т.к. справка не содержит достаточной информации?
На мой взгляд, в работе с Qt, как и с другими библиотеками, необходимо соблюдать контракт. То есть соответствие параметров вызовов и интерпретации возвращаемых значений тому, что написано в хелпе (или документировано еще как-то). Ибо то, что не указано в контракте, может быть изменено. При переходе, скажем, на другую версию библиотеки.
К тому же, нарушение контракта часто может свидетельствовать не о том, что вы знаете и используете "недокументированные возможности", а о наличии ошибки в вашей логике. А это осложняет сопровождение такого кода.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости