Недавно понял, зачем некоторые мейнтейнеры просят делать git squash в репозиториях при слиянии с основной веткой разработки.
воскресенье, 3 июля 2016 г.
пятница, 21 августа 2015 г.
Мой опыт статического анализа кода с PVS-Studio
Имеется у меня графический
движок, с уклоном в разработку игр, который вырос из студенческого проекта
и разрабатывается мной в свободное от основных занятий время.
Писался он изначально
из-за желания изучить OpenGL, и поднять уровень знаний языка C++ и его
инфраструктуры, а также, потому что хотелось написать игру. Игра так и осталась
впереди, а движок пришлось несколько раз переделать, из-за проблем в коде.
Сейчас, я частенько
дописываю те или иные возможности в данном проекте. Со студенческих времен он
сильно изменился: появилась более-менее нормальная архитектура, появились тесты,
которые позволяют худо-бедно проверять стабильность серьезных изменений в
архитектуре проекта, которые нет-нет, да и возникнут.
Статический анализ до
этого я применял на данном проекте, но не срослось с ним: Cppcheck последний
раз, отработав часа три, показал три замечания и все оказались несущественными,
так как могли воспроизвестись только на древних компиляторах.
Начитавшись статей на хабре
и других ресурсах, решил попробовать PVS-Studio и прогнать его из-за интереса
на своем проекте и посмотреть, что из этого получится.
Результаты первого
прохода меня удивили: 80+ ошибок нашлось в главном проекте! Конечно, некоторые
оказались дубликатами или не приводили к серьезным проблемам (пока), но, тем не
менее, исправить предстояло много чего. Конечно же, подвел старый код, в
котором оказалось много проблем:
деструкторы, которые должны были быть виртуальными, отсутствие в
некоторых местах проверок на NULL и прочее. Однако и в относительно новых
участках кода нашлись странные вещи.
Приведу несколько примеров,
чтобы не быть голословным.
Например, оказалось,
что PVS-Studio хорошо находит дублирующие проверки:
Возможно, здесь остались следы от процесса отладки
некого бага, но проверка явно здесь не нужна (animationswayinstance.cpp).
Также обнаружилась целое множество однотипных сообщений
об ошибках:
Оказалось, что проблема находилась в макросе: был
неверно выбран тип поля. Код работал, но расход памяти благодаря замене типа на
правильный сократился (object.h):
Нашлась и куда более серьезная ошибка в самописном
загрузчике формата TGA (tgaloader.cpp).
Ошибка здесь заключается в том, что в сравнениях необходимо
изменить равенство на неравенство, так как это следует из последующего текста. Приятно, что статический анализатор нашел
такую серьезную ошибку.
Ещё интересной подсказкой для меня стало требование замены CreateThread:
Ещё интересной подсказкой для меня стало требование замены CreateThread:
Каким-то образом, я пропустил то, что это API стало deprecated, и было довольно приятно узнать, что его стоит заменить.
PVS-Studio для моего проекта показал гораздо лучшие результаты, чем Cppcheck по количеству найденных ошибок. Хоть здесь и приведены лишь наиболее критичные, но применение данного инструмента позволило мне существенно повысить качество моего небольшого проекта.
четверг, 16 апреля 2015 г.
Hello world!
Вдохновившись замечательным видео, написал хелловорлд на JavaScript.
Вот здесь уже сделали эту задачу и достигли немалых успехов, однако я попробовал повторить подобный успех и попытался минимизировать количество строковых литералов, чисел и символов, используемых в программе.
Впрочем победить вариант по ссылке в виде ёлочки не удалось. Тем не менее, код получился немного непохожим на другие решения, так что прилагаю (запускать в консоли Chrome).
Вот здесь уже сделали эту задачу и достигли немалых успехов, однако я попробовал повторить подобный успех и попытался минимизировать количество строковых литералов, чисел и символов, используемых в программе.
Впрочем победить вариант по ссылке в виде ёлочки не удалось. Тем не менее, код получился немного непохожим на другие решения, так что прилагаю (запускать в консоли Chrome).
среда, 3 декабря 2014 г.
Когда виснет Git под Windows XP
http://billauer.co.il/blog/2012/10/git-pull-windows-freeze-receive-pack/
Я правда просто заменил все вхождения. Работает, проблем не вижу. Что забавнее всего - баг не починен до сих пор.
Labels:
хозяйке на заметку,
Git,
Windows,
WindowsXP
суббота, 22 ноября 2014 г.
Qt + Ruby, Windows XP
Чтобы Qt в Ruby нормально работало по Windows XP сначала нужно поставить гем qtbindings-qt, а уже потом qtbindings. Иначе придется собирать qtbindings вручную, что, к сожалению, очень часто падает и почти никогда не срабатывает нормально.
А еще лучше ставить версию 2.0.0 - она пока на Windows XP работает лучше всего.
понедельник, 30 июня 2014 г.
вторник, 3 июня 2014 г.
Комплексные виджеты в Qt
В довольно древней книге-туториалу по VB.NET описывалось то, как можно создать свой комплексный виджет, состоящий из нескольких подвиджетов на основе встроенного в систему UserControl.
UPD: Можно обойтись и без реализации resizeEvent и moveEvent, если использовать один из наследников QLayout, а виджеты добавлять в него. Спасибо degeron!
В туториалах по Qt есть свой туториал по созданию своих сложных виджетов на основе QWidget. Но он довольно сложный, так как рассчитан на интеграцию в Qt Designer. В итоге разработка своего виджета может показаться сложным и неблагодарным занятием.
Но есть более простой путь. Он заключается в наследовании класса QWidget и переопределении методов void resizeEvent( QResizeEvent * e ), а также void moveEvent( QMoveEvent * e );
При этом достаточно объявить новые виджеты, как поля в новом классе и назначить им родительским виджетом, виджет родительский для данного. В итоге - виджеты будут отображаться и даже реагировать на действия пользователя.
Мини-пример такого виджета на C++ показан ниже.
#include <QWidget>
#include <QTreeWidget>
#include <QTableWidget>
class MyWidget: public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget * parent = NULL);
~MyWidget();
protected:
virtual void resizeEvent(QResizeEvent * e);
virtual void moveEvent(QMoveEvent * e);
void resizeWidgets(const QRect & r);
QTreeWidget * m_tree_view;
QTableWidget * m_element_view;
};
MyWidget::MyWidget(QWidget * parent)
: QWidget(parent)
{
m_tree_view = new QTreeWidget(parent);
m_element_view = new QTableWidget(parent);
resizeWidgets(this->geometry());
}
MyWidget::~MyWidget()
{
delete m_tree_view;
delete m_element_view;
}
void MyWidget::resizeEvent( QResizeEvent * e )
{
QRect oldrect = this->geometry();
QRect r(oldrect.x(), oldrect.y(), e->size().width(), e->size().height());
resizeWidgets(r);
}
void MyWidget::moveEvent( QMoveEvent * e )
{
QRect oldrect = this->geometry();
QRect r(e->pos().x(), e->pos().y(), oldrect.width(), oldrect.height());
resizeWidgets(r);
}
void MyWidget::resizeWidgets(const QRect & r)
{
double halfsizenopad = r.width() / 2.0;
m_tree_view->setGeometry(r.x(), r.y(), halfsizenopad, r.height());
double element_view_x = r.x() + r.width() / 2.0;
m_element_view->setGeometry(element_view_x, r.y(),
halfsizenopad , r.height());
}
Код более серьезного виджета на С++, использующего этот же подход можно посмотреть по ссылкам: [1] [2].
UPD: Можно обойтись и без реализации resizeEvent и moveEvent, если использовать один из наследников QLayout, а виджеты добавлять в него. Спасибо degeron!
Подписаться на:
Сообщения (Atom)





