Меня не покидает когнитивный диссонанс. На форумах обсуждаются возвышенные идеи о написании сверх надежных классов, кто-то рассказывает, что его проект собирается с ключами -Wall -Wextra -pedantic -Weffc++. Господи, где все эти достижения науки и техники? Почему я вижу кругом глупейшие ошибки? Может быть, со мной что-то не так?
Нет, на самом деле я вижу и отличные проекты. Примером может служить библиотека AGLIB. Это весьма интересная библиотека, с точки зрения кода. Пишется она на Паскале, а потом транслируется в C++, C#. Помимо прочих разных преимуществ, такой подход позволяет выловить много разных ошибок, так как одна и та же программа собирается компиляторами для разных языков. В прочем это отдельная история. Возможно, мы как ни будь, напишем с автором этой библиотеки совместную заметку.
Такие приятные исключения, пожалуй, ещё больше усиливают диссонанс. Вот представьте мои ощущения. Я беру сложный пакет численного анализа и не нахожу в нем ошибок. Мне радостно за качественный код. Немного только грустно, что такому человеку PVS-Studio не продать. Ну да ладно. Беру проект OpenCOLLADA. Проверяю. WTF? Других слов я подобрать не могу. Как вам такие конструкторы?
struct short2 { short values[2]; short2(short s1, short s2) { values[0] = s1; values[2] = s2; } .... }; struct double2 { double values[2]; double2( double d1, double d2) { values[0]=d1; values[0]=d2; } .... }
В первом конструкторе промахнулись мимо массива. Во втором скопировали строчку и забыли поменять индекс.
Прости читатель, не могу удержаться от картинки. Она очень точно передает мои эмоции.
«Доставляют» и другие конструкторы. Например, вот это мило:
struct ParserString : public UnionString { ParserString() { UnionString::str = 0; UnionString::length = 0; } ParserString(const int& val) { ParserString(); } };
Вместо вызова другого конструктора, создается и сказу уничтожается временный объект. А члены класса остаются неинициализированными. Подробнее.
Господи, где те люди, которые, засучив рукава, пишут статьи про C++11, лямбды, Boost.Asio, share_ptr, constexpr, LINQ. Почему я вижу в коде:
struct ObjectGroups{ componentList objectGrpCompList; int objectGroupId; short objectGrpColor; void write(FILE* file) const; }* objectGroups; void write(FILE* file) const { size_t size = sizeof(objectGroups)/sizeof(ObjectGroups); for(size_t i=0; i<size; ++i) { objectGroups[i].write(file); if(i+1<size) fprintf(file," "); } }
Поделили размер указателя на размер структуры и получили 0. Что вообще здесь хотели сделать? WTF?
Впрочем, когда даже понятно, что и как хотели записать в файл, от этого не легче.
void write(FILE* file) const { fprintf(file,"%i %i %i %i ", sDivisionCount, tDivisionCount, uDivisionCount, pointCount); size_t size = pointCount*3; for(size_t i; i<size; ++i) { fprintf(file, "%f", points[i]); if(i+1<size) fprintf(file, " "); } }
Если не заметили баг, то я подскажу. Переменная ‘i’ не инициализируется: for(size_t i; i<size; ++i).
Извините, что поделился всем этим с вами. Мне так легче. Заодно, я естественно скажу, что эти ошибки были найдены с помощью статического анализатора кода PVS-Studio. Расположение этих и некоторых других забавных ошибок я выложил вот в этом текстовом файлике. И как всегда, если будут желающие более тщательно проверить этот проект, я готов поделиться ключиком.
Удачи и безбажного вам кода!
ссылка на оригинал статьи http://habrahabr.ru/company/pvs-studio/blog/195928/
Добавить комментарий