Pull to refresh

Comments 221

А оно вообще из trunk работало?
Не знаю. Да это и не важно. Не из-за транка же сотни ошибок. Ну может к релизу парочку бы из перечисленных ошибок поправили. Не более. Почти все из представленных ошибок живут в программах годами и изредка (но сильно) портят жизнь странными невоспроизводимыми глюками и падениями программы.
UFO just landed and posted this here
Virtual method table will be damaged by this.

Порча указателя на таблицу виртуальных методов

Чувствуете разницу?
Тут относительный момент. На самом деле неизвестно, как реализуются виртуальные функции. Таблица теоретически может быть и внутри класса.
В стандартах C++ нет четкого определения как должна реализовываться динамическая координация, но компиляторы зачастую используют некоторые вариации одной и той же базовой модели.
Обычно компилятор создает отдельную vtable для каждого класса. После создания объекта указатель на эту vtable, называемый виртуальный табличный указатель или vpointer, добавляется как скрытый член данного объекта (а зачастую как первый член). Компилятор также генерирует «скрытый» код в конструкторе каждого класса для инициализации vpointer'ов его объектов адресами соответствующей vtable.

Ключевое слово — обычно. В диагностике хотели сказать, что виртуальной таблицей больше пользоваться будет нельзя. Она испорчена. Вернее не она, а указатель на неё. Но никакой разницы нет.
Но вообще спасибо за замечание. Возможно исправим название диагностики.
На самом деле, разница есть. Потому что конструктор производного класса этот указатель исправит. Таким образом, базовый класс не работает, а все производные от него — работают.

Если бы таблица хранилась прямо в объекте, такого бы не произошло (конструктор производного класса исправлял бы только те записи, которые были перегружены).
>> На самом деле, разница есть. Потому что конструктор производного класса этот указатель исправит.

Это настолько деталь реализации, что полагаться на это — не стоит ни разу. Например, в производном классе может не быть виртуальных функций, и нигде в программе нет динамических проверок на данный тип — тогда и указатель не нужно обновлять. Или оно может попробовать дернуть что-то через этот указатель до его обновления. Да мало ли что… U.B. — это U.B., не надо пытаться его обыграть.
Разумеется. Просто в одном случае программа вообще работать не может, а в другом — «вроде работает».
Когда же люди на Rust перейдут?..
Когда создадут параллельный мир, в котором не будет ничего, кроме Rust — это единственный возможный вариант перехода абсолютно всех людей на Rust =)
В таком мире будет слишком большой соблазн изобрести Python.
Кстати, было бы неплохо изобрести его заного. Чтобы сразу третий…
И ещё бы неплохо удалить все системы распространения пакетов в Python и написать единую. Идеальную. С нуля.
UFO just landed and posted this here
По моему, боятся сборки мусора. Там без нее не везде можно обойтись.
UFO just landed and posted this here
Где-то же разбиралось. Одно из мнений было в том, что D опоздал и упустил свой шанс. Если бы он выпустился значительно раньше C++11, то мог бы и взлететь. А сейчас «C++ made right» уже не так интересен по сравнению со всякими Rust. И у него нет киллер-фичи, за которую можно было бы простить слабую экосистему.

А никто не использует — это как посмотреть. Большие продукты™ никто не будет переписывать с /Си.*/ на что-либо ещё. И начинать их писать на маргинальном языке никто не будет. Наколенные проектики — вполне, да, но для больших продуктов™ замкнутый круг. Который можно было бы разорвать, протолкнув ту киллер-фичу, но…
UFO just landed and posted this here
Каждые два года люди говорят, что через два года быть может D взлетит.
Язык клевый, но он правда опоздал.
Будет скопирована только часть строки. Каждый символ строки занимает 2 байта. Значит скопировать надо 14 байт, а не 7.

Интереса ради, в C++ используют суррогатные пары в wchar (т. е. символ u+00010000 и выше, представленный двумя wchar)?
UFO just landed and posted this here
Кстати говоря, на *NIX платформах обычно sizeof(wchar_t) == 4. Ещё один аргумент в пользу никогда не использовать wchar_t, если в программе используется более одной кодировки текста.
Нынче модны char16_t и char32_t.
Обыкновенные char и uint8_t всегда в моде. И таки можно всегда хранить внутри все строки в utf8 и конвертировать на границе ответственности.
Тут проблема в том, что две основные десктопные ОС хотят именно UTF-16, а конвертирование несколько неудобно, да и накладные расходы добавляет. Хотя жизнь, несомненно, была бы проще, если бы везде было UTF-8.
Посмотрел на _NET_* свойства, они хотят utf-8… Или вы про другую вторую ОС с NSString в utf-16?

Перекодировать из utf-8 (который вполне удобен как для сети, так и для работы внутри) в ucs-2 для символов до u+7f тривиально, до u+7fff просто. Если нужно дальше, то генерировать суррогатные пары — не велик труд. Так что накладных расходов копейки (основные — лишнее выделение памяти). Но при этом неплохо экономится память на ascii-текстах и нервы при передаче по сети (где utf-8 куда интереснее utf-16, т. к. не надо думать об endianess).

Хотя для внешнего обмена и хранения мне очень нравится BOCU-1, но у неё есть одна проблема, и имя ей — IBM. Для индексов lucene/solr оно выглядит очень интересно (т. к. позволяет хранить мультиязычный текст с плотностью около 1 байта на символ для символов, представимых в однобайтной кодировке).
Хотя жизнь, несомненно, была бы проще, если бы везде было UTF-8.
С символами, занимающими от одного до шести байтов?
Сомнительное упрощение.
А какая вам разница, что по одной-две единицы хранения на символ (UTF-16), что по одной-шести (UTF-8)? Что так, что так нужно работать с переменной длиной.

Зато в UTF-8 этот факт почти для всех очевиден. А вот UTF-16 для очень многих символов позволяет допущение одно слово = один символ, и в итоге люди пишут сломанный код, не зная об этом.
А какая вам разница, что по одной-две единицы хранения на символ (UTF-16), что по одной-шести (UTF-8)?
После появления суррогатных пар в UTF-16 всё стало не так радужно, конечно, но и отчего жизнь стала бы вдруг проще при повсеместной победе UTF-8 мне тоже не ясно. Вот UCS-4 — другое дело, но он очень уж затратный по памяти.
Зато в UTF-8 этот факт почти для всех очевиден.
Для тех, чей родной язык/язык повседневного общения использует для письма только символы из первой половины ASCII-таблицы, это далеко не всегда очевидно.
С ходу найденный пример: http://stackoverflow.com/q/6257818/882813
И подобных вопросов там немало.
Ну согласитесь все же, что языков с символами только из ASCII все же в разы меньше, чем таковых из UCS2. Собственно, мне, кроме английского, ничего в голову не приходит — да и там встречаются слова вроде naïve, плюс заимствования из испанского с ñ в американском английском.
После появления суррогатных пар в UTF-16 всё стало не так радужно, конечно, но и отчего жизнь стала бы вдруг проще при повсеместной победе UTF-8 мне тоже не ясно.
У utf-8 есть ещё бонус, что его представление не зависит от host endianess. В случае utf-16 это не так (из-за чего и существует bom), что приводит к лишним конверсиям на одной стороне: на современных процессорах это всего лишь дополнительные 1-3 такта на символ, на тех, что не поддерживает swap может быть куда дороже.
Справедливости ради, представление UTF-16 LE тоже не зависит от host endianess. И UTF-16 BE не зависит. Надо было создателям стандарта бросить кубики и выбрать одну из этих двух кодировок вместо придумывания bom-а.
Нет, если endianess строки в памяти не совпадает с endianess платформы, вся сложность переехала бы в софт, который делает посимвольную обработку. Наример, ф-цию
vector<utf18be_string> split(const utf18be_string& line, uint16_t separator);
нужно было бы вызывать не как
split(aLine, ':'),
а как
split(aLine, TO_UTF16BE_CHAR(':'));

Все коды символов в текстовой записи (не в бинарной, где можно договориться до BE), хранимые в базах/конфигах или получаемые по сети (например, HTML "& #58;") нужно было бы конвертить в big endianess перед тем, как использовать в посимвольной обработке.
Можно было бы объявить функцию как vector<utf16be_string> split(const utf16be_string& line, char16_t separator); и вызывать как split(aLine, L':').

Строка в памяти — это просто массив символов. Ее посимвольная обработка никак не будет отличаться на разных платформах, потому что это всего лишь обработка массива.

Действительно различалась бы в таком случае обработка отдельных символов. Так, если для преобразования арабской цифры в число достаточно выполнить проверку ('0' <= ch && ch <= '9') и потом преобразование (ch — '0') — то на платформе с отличающейся endianess пришлось бы делать что-то более сложное.

С другой стороны, проще корректировать endianess в процессе ввода-вывода, и хранить строки в памяти всегда в наиболее удобном формате. Тем более, что сейчас так и делается — и я не виду причин, по которым все усложнилось бы просто из-за исчезновения из мира лишней кодировки.
Можно было бы объявить функцию как vector<utf16be_string> split(const utf16be_string& line, char16_t separator); и вызывать как split(aLine, L':').

А если разделитель лежит как первый символ строки aLine или в любой другой строке:
split(aLine, CHAR_BE_TO_CHAR_W(aLine[0]))

я не виду причин, по которым все усложнилось бы просто из-за исчезновения из мира лишней кодировки.

Это не просто произвольная кодировка, ничем не лучшая других аналогичных. У неё есть особенность — она с нативным для архитектуры endianess.
Это не просто произвольная кодировка, ничем не лучшая других аналогичных. У неё есть особенность — она с нативным для архитектуры endianess.
Вы так говорите, как будто строка в памяти обязана иметь кодировку.
Просто хранение — редкая задача. Часто нужна минимальная обработка.
Например, для определения длины строки, важна кодировка.
Я не предлагаю хранить строку как попало. Я предлагаю скрыть все подробности хранения в стандартной библиотеке, чтобы «на выходе» строка была всего лишь последовательностью символов, независимо от способа хранения этих символов. И обрабатывать строку надо как последовательность абстрактных символов, а не байт.

А вот именно при хранении строки, или при передаче — и возникает понятие кодировки.
Так можно. Но незнание представления в памяти породит оверхед там, где он не нужен. Тот же доступ str[i] может делать bswap, а может не делать.
вместо придумывания bom

BOM по хорошему нужен и для UTF-8 (камень в огород тех кто говорит что он ему не нужен), ибо не во всех случаях костыли для определения UTF-8 работают. Стоит влезть какому-нибудь NUL или ещё чем-нибудь из подобного рода и капец, пока не включишь подсветку таких знаков и не найдёшь или не пройдёшься (созданной горьким опытом) регуляркой, фиг поймёшь в чём проблема.
Вот регулярка кстати, вдруг кому-нибудь пригодится:
(\0|\x01|\x02|\x03|\x04|\x05|\x06|\x07|\x08|\x0B|\x0C|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F|\x7F)

Прогоняю обычно через Notepad++.

А между прочим у меня была ещё такая ситуация когда такие служебные знаки должны быть в тексте (отладочном), при этом должны соседствовать с UTF-8 строками. Когда вот BOM добавишь всё хорошо, а без него везде слетает в ANSI.
костыли для определения UTF-8 работают
Вы либо знаете кодировку текста (utf8, utf16, какое-нибудь хитрое cjk или очередная однобайтная копрофосилия мамонта типа cpxxxx), либо определяете её эвристически (по статистике n-грамм, например). Наличие 0xfffe или 0xfeff в начале файла не говорит ничего о кодировке. Может там текст в cp1251 начинается с «яю»/«юя»?

BOM (byte order mark, напомню) нужен, чтобы определить endianess системы, на которой текущее байтовое представление было нативным для int16_t (ucs-2, utf-16) или int32_t (utf-32). Он не является прямым признаком используемой кодировки. Чтобы его интерпретировать нужно знать кодировку данного набора байт заранее.

А между прочим у меня была ещё такая ситуация когда такие служебные знаки должны быть в тексте (отладочном), при этом должны соседствовать с UTF-8 строками. Когда вот BOM добавишь всё хорошо, а без него везде слетает в ANSI.
Это паркетно-половые трудности используемых редакторов и некоторая «особенность» одной ОС. Эта же ОС, например, рапортует, что у неё в консоли cp866/ibm866, а имена файлов из этой же консоли передаёт перекодированными в cp1251. Happy debug, как говорится.
Сложно жить с utf-1, благо она не взлетела. А utf-8 самосинхронизируется. И поиск начала следующего codepoint'а не сложнее, чем проверка на суррогатность пары в utf-16
Видимо именно поэтому я перестал ей пользоваться, ибо текло и падало.
Ну так Вы же программист. Никто не мешал провести отладку. От этого и Вам и людям польза. Людям то что их любимая Miranda NG стабильнее, а Вам дополнительная строчка в резюме. Замечу хвалиться достижениями сделанными в коммерческих проектах очень сложно ибо NDA и др., а вот то что сделано в OpenSource очень даже помогает при собеседованиях!
Если я буду допиливать чужие проекты, мне не останется времени на свои.
А вы считайте чужие, которые дорабатывайте, своими :)
Ага, а свои, на которые не хватило времени, чужими.
Извините за возможно глупый вопрос, но тем не менее: можете пояснить проекты, которые Вы называете «своими»?
Все просто на самом деле. Любой человек каждый день проходит мимо глупости, не оптимальных решений, не решенных проблем. Просто проходит мимо.
Конечно наш мир стал бы лучше если бы все видя лежащий на земле мусор доносили бы его до ближайшей мусорки, помогали бы всем встреченным нуждающимся в помощи, ремонтировали бы механизмы. Но все это можно делать только за счет своих личных времени и сил. Аналогия думаю ясна.
Ох, если бы все сантехники чинили все унитазы, которыми им приходится пользоваться, например в общественных туалетах…
UFO just landed and posted this here
UFO just landed and posted this here
Раз вы не понимаете, за что минусы — расскажу, хотя и не хотел заниматься декларациями очевидного. Кстати, минус вместо комментария зачастую «прилетает» именно от нежелания писать банальность в 100500й раз, а не от желания нагадить.

Банальность
Если у кого-то программа работает — это еще не значит, что она будет работать у всех. Дело не только в количестве протоколов или включенных плагинов, работоспособность зависит еще от многих других причин. Например, от сервера, к которому вы подключаетесь. Даже для закрытой-презакрытой аськи существуют прокси-серверы (не знаю, что именно они делают, но ни раз видел инструкцию вида «как выйти в аську из нашей локалки») — а другой сервер может немного по-другому использовать протокол, что приведет к активации других ветвей выполнения программы. Я уже не говорю про протокол XMPP, который настолько расширяемый, что у каждого сервера появляются свои особенности.

Проявится баг или нет, может зависеть от того, какие мессенджеры используют контакты из вашего списка, какую информацию они указали у себя в профиле. Оно может зависеть, элементарно, от длины сообщений, которые вам посылают. Поэтому тот факт, что у вас все заработало «искаропки», совсем не означает, что у другого человека она проработает дольше 5 минут.

Разумеется, все это не означает, что Миранда должна падать у всех. В конце концов, этот мессенджер живет уже кучу лет, оставаясь при этом на слуху — а значит, он обязан «в целом скорее работать, чем падать». Более того, поскольку (со слов Ivan_83) разработчики Miranda NG собирают крешдампы — все оставшиеся баги возникают достаточно редко, частые баги давно починили.

Однако, все эти выявленные анализатором места — это запах кода. Плотность таких глупых ошибок при написании кода в целом постоянна — и если в каких-то ветках их уже нет — значит, они там были. Каким образом они могли исчезнуть? Их могли найти в процессе отладки, тестирования или эксплуатации. Но программисты, пишущие такое, отладкой и тестированием обычно не заморачиваются. Следовательно, они были выявлены в процессе эксплуатации, то есть когда-то Миранда действительно текла и падала. И причина этих утечек и падений — именно в тех самых «диких указателях», раскрытых в статье.

PS Вы вот в комментарии ниже обвиняете оппонентов в «кармадрочестве» — а сами при этом не забываете смотреть на свои циферки :) Позвольте дать совет. Одиночный комментарий может собрать хоть -100 — но при этом, если он является корректным (не содержит оскорблений и полного бреда, а также имеет внутри хоть какую-то смысловую нагрузку) — в карму, как правило, прилетает не больше трех минусов. А вот если оскорблять собеседников, или отказываться читать их сообщения, говоря одно и то же по 10 раз — то комментирование раз в пять минут практически гарантировано.
UFO just landed and posted this here
Не буду говорить про пафос. Скажу про то, что видно — гадкие люди тоже любят уезжать из России, это радует. Эти 10-50-100% денег ничего стоить не будут, когда ЯБ будет над головой пролетать.

Ах… да, думаю тупость будет публике видна даже в том, что субъект пишет на русском портале. При этом его ненавидя. Клоун, что с него еще взять?

Лучше бы следил за йеллоустоуном.
UFO just landed and posted this here
> element->getAttribute(L"href", 2, &variant)
Тут еще один баг, IHTMLElement::getAttribute в качестве аргумента ожидает BSTR, а не wchar_t*. На моей практике этот метод не падает, но думаю только потому, что в MS написали дебилоустойчивый код.

Показывает ли Ваш анализатор этот момент?
Пока нет. У нас подобные диагностики в todo записаны, но до них никак руки не дойдут. Там правда много полуложных срабатываний будет. Многие не различают BSTR и wchar_t * и хранят как попало. Но работаю только как с wchar_t * (т.е. BSTR им не нужен на самом деле). И поэтому программа работает.
Там проблема еще в том, что BSTR — это и есть wchar_t*, с т.з. типов. MSDN:
typedef WCHAR OLECHAR;
typedef OLECHAR* BSTR;
typedef BSTR* LPBSTR;


А то, что в контракт там входит еще и длина, это есть только на уровне документации.
Опубликовал ссылку на статью в Miranda NG Software в Facebook. Ответили:
PVS constantly tries to PR using Miranda but PVS itself is too ugly to detect any real problem. none of these 'problems' really affect the program execution.

А потом кажись и ссылку удалили. Хм… Ну с таким подходом… Я переживаю за качество. :)

P.S. Эксперт, который за 5 минут смог сделать вывод что всё ok, ещё бугогашечки из второй статьи не видел. :)

Ну чем не красоты:

_tcscpy(src, src);

for (i = MAX_PATH; 5; i--){

Но всему своё время. Не всё сразу.

Похоже что просто обиделись, бывает :)
Как по мне, так статический анализ – то, что действительно помогает перенести значительную часть внимания на идею и меньше думать о реализации. Может это сомнительное дело, вроде «пусть за меня думает компилятор», но в жизни нередко имеет место быть.
Обидеться на подобный баг репорт — это просто расписаться в собственной некомпетенции и поставить крест на себе как на профессионале.
Как-то все противоречиво. За такие баг репорты, с указанием конктретного места в коде и разбором полетов, нужно деньги предлагать, а не обижаться.
Там картинка в сообществе показательная. :)
Это отписка «ничего не знаем, у нас всё работает!»
Строго говоря они правы, во-первых, вы проверяете код не случайного васи пупкина, а известного проекта, стало быть это пиар, во-вторых, вы могли бы отправить им отчет и не писать никакой статьи и сохранили бы имидж проекта и помогли бы ему, т.е. снова пиар, в-третьих, сам тон статьи крайне пренебрежительный, это было бы справедливо в отношении платного софта, но никак не опенсурс, люди работают за идею и не просят за это денег, в отличие от вас.

И вместо того, чтобы осознать это, вы продолжаете:
> P.S. Эксперт, который за 5 минут смог сделать вывод что всё ok, ещё бугогашечки из второй статьи не видел. :)

Никого не оправдываю, но призываю к пониманию.
Им нашли кучу ошибок. Не так разве? А они вместо того, чтобы принять их к сведенью, обиделись.
Я понимаю, что что мы как приносим пользу своими проверками, так и несём людям негативную энергию. Приходится показывать людям неприятные вещи. К сожалению (радости) этот вид рекламы работает, а значит мы будем продолжать этим заниматься. Как говорится, ничего личного, просто бизнес.

Проверять и втихомолку отправлять отчёт нам смысла нет. Про отчёт узнает человек 10-20. Если они расскажут кому-то ещё, ну человек 100. Не будет никто про это статью писать, так что никакой 1000 читателей не будет. А вот эту статью читают тысячи. Десятки и тысячи читателей сравнивать нельзя.

Кстати, чтобы найти все описанные в статье ошибки будет достаточно и CppCat (третий уровень GA в PVS-Studio и прочие диагностики я всё равно не смотрел). Я думаю, среди разработчиков Miranda NG, найдется пара студентов, которые воспользуются нашим предложение и прошерстят проект. См. Бесплатный CppCat для студентов.
Всё это хорошо и правильно, только не забывайте, что мы все люди, и не каждый может отделить критику своей работы от личной обиды. Open Source для многих – любимое хобби, как выращивание цветов или лепка глиняных котиков, и здесь как раз-таки стоит постараться обойтись без «негативной энергии».
UFO just landed and posted this here
А что ещё можно ожидать в отчёте об использовании программы, которая создана для того, чтобы искать ошибки людей, не умеющих писать идеальный код с первого раза, и тыкать в них носом, чтобы они больше не повторялись?

Вот так?
Моя подруга с её парнем писали плагин к Miranda NG, я настоятельно не рекомендую им делать <так-то>

Или так?
Я добрался до проекта Мессенджер_1 и проверил его с помощью анализатора кода PVS-Studio. К сожалению, с точки зрения работы с памятью и указателями это самый неаккуратный проект из виданных мной.

<...>

Типичный пример:

void API_2 Function_234(Class_23 *var_1)
{
  ....
  HWND handle = var_1->handle;
  ....
  if (var_1 == 0 || handle == 0) { return; }
  ....
}


Предупреждение PVS-Studio: V595 The 'var_1' pointer was utilized before it was verified against nullptr. Check lines: 428, 430. Plugin_8 source_file_42.cpp 428

Неумение или нежелание отделять код от личности его автора — это ребячество. В статье нет ни одного прямого наезда на конкретных Джонов и Иванов, которые писали это код. Я думаю, уничижительный стиль вызван именно отвращением к качеству самого коду, а не к качествам разработчиков.

Не важно, кто пишет код. Если это плохой код, его открытость и популярность — это отнюдь не оправдание. Только показатель того, какой части разработчиков безразлично качество кода. А воспринимать ли наезд на всё сообщество разработчиков как личное оскорбление — это зависит от того, осознаёт ли разработчик свою личную ответственность за замеченный, но не прибранный срач в куске кода по соседству. Коллективная безответственность творит чудеса.
UFO just landed and posted this here
Статический анализатор именно что тыкает носом. Он не говорит вам идти и исправлять код, только: «Я вижу в строке 428 неправильное использование указателей».

Статья же указывает на ошибки и даже даёт как разъяснения по некоторым проблемам (не делать больше так, как написано), так и конструктивные предложения по проекту вообще: использовать статические анализаторы, желательно сами-знаете-чей; и в один из следующих релизов запланировать чуть меньше перделок и чуть больше рефакторинга. Ну и да, выражает личное отвращение автора.

я карму не минусовал.)
UFO just landed and posted this here
PR-щик коммерческого продукта даже не дал себе труд воспользоваться MirandaNG

Извините, что влезаю — но зачем? Что это докажет? Есть некоорая ошибка, которая при определенном стечении обстоятельств может привести к сбою. В течение этих двух дней она почти наверняка не проявится. Смысл?

P.S. «сперва добейся» не работает.
UFO just landed and posted this here
UFO just landed and posted this here
Строго говоря, они все-таки не правы. Во-первых, каким бы ни был тон статьи, нет смысла отказываться от бесплатной помощи. Во-вторых, проблемы в статье описаны достаточно серьезные. Самое глупое, что можно сделать в этой ситуации — написать: «none of these 'problems' really affect the program execution». Прямо классика жанра.

Из опыта могу представить, сколько мелких баков, протечек и неожиданных вылетов можно исправить просто пробежавшись по составленному списку. Работа с указателями — это все-таки работа с указателями. Иногда ошибку с затиранием какого-нибудь указателя можно искать всей командой неделю, был у меня такой случай. Проект большой, все на указателях. Где-то портился указатель на метод в объекте. Проявлялось редко и рандомно. Ушла неделя на то, чтобы найти выход за границу выделенной памяти при копировании блоков.

А пиар… Много всего делается ради пиара. Когда магазин ради пиара устраивает распродажу со скидками, глупо этим не воспользоваться. Про «бесплатно» и говорить нечего. Умные люди и из этого могли бы извлечь выгоду, пропиариться в ответ: «Мы исправили 146% багов и теперь Миранда стала еще надежней».
Товарищ Yaruson грамотно все описал, так как люди тратят свое личное время, они могут себе позволить нерациональные решения, но этого всего можно было легко избежать.

Я вам предлагаю даже эксперимент, громко объявите на весь оффис, что класс (допустим там будет баг), который написал ваш коллега — это худший код, котрый вы видели за всю вашу карьеру :)
так как люди тратят свое личное время, они могут себе позволить нерациональные решения

Напомнило мне одну историю. Там водитель предлагал куда-то бегущей сотруднице подвезти ее. На что она ответила: «Мне некогда, я спешу».
я думаю, что вы меня поняли.
Да, понял. Просто я заострил внимание на одной стороне, вы — на другой. Думаю, обе стороны могли бы повести себя лучше. Пожалуй, извлеку и для себя урок.
Вы понимаете, что общественное порицание — это «бесплатная» помощь? Ооо, я знаю много людей, даже наверное я сам, отказался бы от такой бесплатной помощи.
А по моему они правы. Они удалили ссылку на негативный пиар своего продукта. Исправят они баги или нет — неизвестно. Если не исправят — вот тогда они будут не правы.
Возможно, я не прав, но одним из ключевых преимуществ опенсурса как раз приводят всегда то, что код открыт и любой может его проверить, что повышает доверие к продукту.

В данном случае ребята получили крутейший способ пропиариться, и так убого его испортили.

Offtopic: есть старый анекдот, как русские начали красить луну в красный (коммунистический) цвет, а амеры этим воспользовались, написав белым Coca-Cola.

В данном случае ребята из Миранды вместо того, чтобы взять в руки кисть и довершить рекламу такого масштаба (малыми ресурсами добившись многого), начали тулить непонятные отмазки
В данном случае ребята из Миранды вместо того, чтобы взять в руки кисть и довершить рекламу такого масштаба (малыми ресурсами добившись многого), начали тулить непонятные отмазки

всё уже исправаили
Да. Я сказал «кажись». Просто Facebook странно показывает ленту. Моё сообщение скрылось для меня и я решил, что его удалили.
Просто фейспалм.
Ссылка-то, может и есть, но в ленте я этого не вижу.
Теперь вижу. А куда делось 80% сообщения?.. Впрочем, этот вопрос надо не вам задавать…
Оно всё там, по клику раскрывается.
Складывается впечатление, что к проекту приложили руку школьники, которые C++ недавно увидели.
Вы абсолютно правы, более того многие «школьники» С++ и не видели. Я по крайней мере не видел, и учился во время разработки.

Вообще там все написано на «Си с плюсовым синтаксисом».

И перефразируя «это опенсоурс детка, тут и говнокодить могут». Вы бы еще по моим курсовым 10 летней давности PVS студией прошлись бы.

З.Ы, кстати на моем рабочем проекте демоверсия тупо в корки упало, но я же не кричу об этом на каждом углу.
Одно дело курсовая, другое — массовый продукт.
:) Опенсорс — это не массовый продукт, это Опенсорс. Кто то пишет курсовые, кто то учиться кодить.
Вас никто не заставляет им пользоваться, никто не навязывает, никто не продает, никто ничего не обещает. Я вот при написании clist_modern откровенно учился программировать, экспериментировал с WinApi и с разными недокументированными вещами. Когда научился — перестал писать для миранды.

Я этого никогда не скрывал, и скрывать не собираюсь. Да мне сейчас стыдно за свой код. Но это код был учебным. Я конечно мог поступить наоборот и никому не показывать свой код. И все мирандовцы могли. Этой статьи бы не было, но код бы лучше от этого не стал.
Т.е. опенсорс не предполагается нигде использовать? Его создают исключительно ради самого процесса написания?
Ну кто как. Я лично создавал свой модуль исключительно для себя. Потом появились люди которым он понравился им тоже стали пользоваться. Они присылали какие то замечания которые по возможности исправлялись, какие то новые баги писались. Я его создавал именно ради самого процесса написания. Ну и мне хотелось иметь полупрозрачное окно мессенджера с различными шкурками еще в эпоху windows 9x/XP. Но опять таки для себя. Я не зажал ни код, ни модуль. Поделился чем имел. Это и есть мир настоящего опенсорс.
Чтобы учиться программировать, нельзя писать программы в стол. Чем большее количество людей пользуется той поделкой которую ты написал, тем больше фидбэка ты получаешь. И опенсорс в таком ключе мне кажется идеальным вариантом.

Плюс и у опенсорса должны же быть какие то правила приема патчей и тд, чтобы откровенный говнокод не попадал в транк, и это тоже способствует обучению гораздо больше чем 100к строк написанных в стол.

А тот же «Google Summer of Code» вас не смущает, когда опенсорс целенаправленно используется для обучения студентов и от которого обе стороны только выигрывают
UFO just landed and posted this here
Ну постгрес это постгрес. Я понимаю если бы тот же Гоша за каждый ответ на вопрос «как в настройках миранды включить вот это» просил бы хотя бы $1. Ну или хоть какой то платный саппорт. Или если бы была модерация патчей в миранде — то не было бы такого… разнообразия модулей, в чем и есть ее популярность.

>> это опенсоурс детка, тут и говнокодить могут
А в проприетарных конечно не могут, там же не люди сидят, а волшебные феи.
Могут и там и там. Просто отбор в opensource гораздо ниже. В проприетарных хоть какое-то собеседование проводят прежде чем допустить работника к коду.
Ничего не имею против Индии и ее населения, но вот код, произведенный ими иногда поражает. Да, в коммерческих проектах.
Ну вот, кто-то пришел и начал молча минусовать в карму.
Спасибо конечно за багрепорт (своих строчек вроде не увидел :) )

Мы это ценим, уважаем и любим. Вот если бы еще патч приложили :) Правда практика показывает, что толку от вашего анализа чуть… после первого же фрагмента перестал читать дальше — так проглядывал: Как вы думаете если у нескольких миллионов пользователей за несколько лет в этом месте ничего не падало, то каковы шансы что этот указатель окажется NULL?

А прежде чем обвинять канал Miranda NG Software в Facebook, научитесь пользоваться FB :) никто ничего не удалял:

www.facebook.com/miranda.newgen/posts/1255536397803385
Я не раз видел, как работал код, который работать не мог в принципе. А потом, как правило, оказывалось, что вокруг прикреплено куча костылей для того, что бы все работало нормально, не смотря на этот баг.
Я к тому, что если и так все работает, то это не повод оставлять явную ошибку в коде.
Кстати, в следующей статье будет красивый пример сдвоенного бага. Баг — переменная может остаться неинициализированной. Но из-за второй ошибки (не там поставленной скобка в условии), она инициализируется всегда. Одна ошибка исчезает и код типа даже иногда работает. :)
Не в следующей, а в этой же. Третьим по счету вы его показали.
Ой. Действительно. Перепутал.
код типа даже иногда работает. :)

В том примере, что вы описали, код работает всегда, а точнее программа работает правильно, только никто не говорит, что это правильно написанная программа.

В хорошо оттестированном продукте статитеческий анализатор больше находит как не надо писать код, а не сами ошибки продукта.
Ну и что, что говно в коде. Все ж работает!
Да, тоже хотел сказать — не оспаривая выводы статьи, ради справедливости замечу, что Miranda NG, в отличие от предыдущей Миранды, не падала у меня пока ни разу за несколько месяцев, которые помню. При том, что запущена постоянно, с разными плагинами.
А вот у меня падала и не раз и внезапно по стабильности была хуже IM и это совсем недавно. Так что это у кого как.
И это я вовсе не имею ввиду что IM хороша, а NG плоха, просто проблемы у NG тоже есть (хотя будущее определённо за NG, с этим даже никто не спорит).
Я смотрю, у Вас там единый стиль, что в написании кода, что в общении с оппонентами. Жаль, очень, правда. Большая удача, когда кто-то указывает тебе на твои ошибки, а не ждет с ухмылкой когда ты потонешь.
Как вы думаете если у нескольких миллионов пользователей за несколько лет в этом месте ничего не падало, то каковы шансы что этот указатель окажется NULL?

Лучше перефразировать вопрос, каковы шансы что RequestStatus() будет вызван успешно? Абсолютно никаких. Такое отношение к разработке наводит на некоторые мысли.
Божтымой, святая простота-то какая. мимими.

Т.е. вот прям так взять и при всём честном народе сказать "мы пишем одноразовый код, который никогда не будем рефакторить". Будем сидеть и бояться дышать на легаси код, потому что там живут огнедышащие тараканы. А когда достигнете критической массы костылей и заплаток — так, что любой чих в коде будет вызывать непредсказуемые (причем зачастую отложенные) последстия в совершенно не связанных с ним (казалось бы) областях, то… А, я знаю! Сделаете ещё один форк со словами "там всё плохо, а вот теперь-то мы всё сделаем как надо!", да?
:) вы забавны. Цитирую буквально свой статус в jabber в эпоху разработки: «Пошел нафиг дальше баги писать. ВирандаИМ — Больше, тормознутее, глюкавее.»

А разработчики иначе как «стройной системой костылей и подпорок» ее и не называли"
У вас, товарищ, забавноуказатель инвертировался.

Нормальной реакцией было бы "о! руки не доходили, а тут уже за нас сделали. спасибо, надо глянуть".
Вместо этого — попытки огрызаться из разряда "самдурак", вялые оправдания "вы бы видели, что там РАНЬШЕ было!" и тому подобное.
Все ж, вроде, взрослые люди. Понимают, что в опенсурсе может быть что угодно. Тем более, если этому опенсурсу столько лет и он столько раз испытывал боль перерождения. Чо оправдываться-то? Поблагодарить, взять на заметку и пользоваться, пока другие за вас работу делают. Удобно ведь, нет?

А позиция "у всех работает" просто наивна. Довольно толстый проект без единого юнит-теста, живущий на соплях вида "уф, собралось!", даже без вменяемой обратной связи… Когда сообразительному пользователю надоедает, что миранда падает на каждый чих — он выясняет, какой плагин виноват и отключает/обновляет/заменяет его. Если же пользователь ленив или недостаточно технически подкован — он просто сносит миранду к чертям и пользуется чем-нибудь ещё. В обоих случаях вы НИЧЕГО об этом не узнаёте и дальше радостно празднуете "стабильные релизы". И только самые дотошные продираются через дебри «поддержки» на форуме, чтоб оставить багрепорт и заметить, что предыдущее сообщение было пару-тройку лет назад. Т.е. этот плагин вообще никто давно не тащит на себе.

А кичиться багодельней — вообще детсад. "Нашла, дура, чем гордиться".
UFO just landed and posted this here
По сути, на проект никто не наезжал. Да, автор статьи мог бы и уделить хотя бы пару слов оговорке, что это доисторический проект с жутко разнородной толпой абсолютно никак не организованных контрибуторов — тогда хотя бы выглядело не так ультимативно.
Однако, здесь уже (если пойти от моего комментария вверх и посмотреть, кто же начал эту ветку) речь идёт не о проекте в целом, а о позиции одного конкретнов взятого персонажа, который первым заговорил от лица разработчиков проекта, попутро неся чушь и поливая фекалиями всех вокруг.
И вдогонку: я думаю, этому персонажу уже итак довольно доходчиво объяснили степень его заблуждений относительно подхода к разработке.
Я рад, если на проекте есть вменяемые люди, которые хотят и пытаются что-то сделать. Но реальность такова, что в коде — одна сплошная большая ягодичная мышца. Обижаться тут не на что- это просто факт.

А вот автору добавить в статью пару слов про дремучую опенсурсность, я думаю, не сложно.
За «персонажа» личное спасибо :)
И про подход к разработке у «персонажа» несколько отличается для свободного OpenSource, для коммерческого OpenSource, и для проприетарного кода.
И кстати «персонаж» уже 4 года никакого отношения (ну кроме моральной поддержки) ни к проекту Miranda IM, ни к проекту Miranda NG не имеет.
UFO just landed and posted this here
никто не вызывает эту функцию передавая туда NULL.

Извините, но эта фраза не очень хорошо Вас характеризует
Не буду подробно комментировать. Замечу только пару моментов. Я беру и проверяю проекты. Их много и вникать в каждый и разбираться, что надо проверять, а что нет, я не буду. Кому-то везёт, кому-то нет. :)
А по поводу return(""), предлагаю подумать и подучить Си++. Это корректный код.
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
А не из-за проблем ли с кодом оригинальной Miranda IM появилась Miranda NG?

Ваши же принципы, разве нет?
Принципы проекта:
Прекращена поддержка версий ANSI, как полностью морально устаревших. Будут только Unicode (x32 и x64-версии).
Поддерживаются только компиляторы Visual Studio 2010, 2013.
Подключение и отключение плагинов «на лету», без перезапуска программы.
Все плагины находятся в одном репозитории, при изменениях в ядре необходимые правки вносятся сразу, без ожидания реакции разработчиков, которая может длиться месяцами у Miranda IM.
Проведена достаточно большая работа по унификации — многое из того, что каждый плагин реализовывал самостоятельно, было перенесено в ядро.
Избавление от старых «костылей» и багов, повышающее общую стабильность программы, повышена скорость запуска и работы программы.
Возвращение в разработку Miranda NG разработчиков, покинувших или бросивших по тем или иным причинам разработку плагинов под Miranda IM.
Расфиксировать на время API плагинов.[12] Это значит, что некоторое время разработка новых плагинов будет невозможна (будут работать только те, что лежат в репозитории и централизованно обновляются). Это даст чистое API, которое впоследствии можно будет и заморозить.


В чем тогда смысл идти таким же путем?
Даже не знаю с чего начать, некто Георгий Хазан смог бы подробнее описать. Но основной мотив был политический — товарищи из Miranda IM ну откровенно достали. В итоге те разработчики модулей что были послабее духовно или позанятее — бросили код. Например я — просто пропал интерес к IM, к разработке интерфейсов, просто к OpenSource.
С учетом того что основная масса разработчиков из наших включая фактически основного разработчика ядра и чистильщика авгиевых конюшен — Гоше удалось соорганизовать оставшихся и собрать код воедино и тащить его на себе.
Лично я бы это не осилил. Вы не представляете сколько он откровенного… оттуда выгреб. Но сколько еще там осталось. Поэтому я с изрядным скепсисом отношусь к этой статье, ничуть не умаляя заслуг статистических анализаторов.
Правда практика показывает, что толку от вашего анализа чуть… после первого же фрагмента перестал читать дальше — так проглядывал
ничуть не умаляя заслуг статистических анализаторов.
Не понял сарказма. Для меня разницы нет между PVS (за который надо платить деньги) и warning Visual Studio (за который деньги уже плачены) или warning gcc или clang (за которые платить не надо).

Да это инструмент, который может решить какую то задачу. Беда в том, что инструмент ничего не гарантирует, в том что -W4 решит ее лишь немногим хуже. Зато инструмент гарантированно добавляет работы: надо же разобраться корректно ли его предупреждение в данном конкретном случае, не повлечет ли исправление изменений в логике работы ибо даже здесь в комментах были проблемы двойных ошибок. Технически анализвтор вторую мог не найти и код после исправления ошибки начал бы падать в другом месте, а так как ошибка довольно специфическая падал бы он еще «иногда» редко и при невыясненных сценариях.

Лучше стоимость этого продукта и свои силы на его внедрение вложить в совершенствование процесса разработки (проектирование, ревью кода, юнит тестирование, ТДД, ), дополнительное обучение сотрудников (теже паттерны, стандартные библиотеки, ООП), найм более опытных сотрудников, лишний сервер под юнит тестирование.

А присвоение в if мне и grep найдет.
Для меня разницы нет между PVS (за который надо платить деньги) и warning Visual Studio (за который деньги уже плачены) или warning gcc или clang (за которые платить не надо).

Компиляторы от части уже реализуют статический анализ кода и выдают предупреждения. Именно warning, так-как если бы компилятор был уверен, что код ошибочен, он бы выдал error. И именно поэтому у предупреждений компиляторов есть уровни. Они задают порог вероятности, что компилятор выдаст не ложное сообщение.

А разница в том, что статические анализаторы — это специализированные инструменты, а анализ в компиляторах в любом случае делается по остаточному принципу. Грубая аналогия — есть Paint встроенный в Windows и есть профессиональный Photoshop. Замечательно что есть Paint и для многих задач его достаточно. Но если вы задумали серьезное, то вам понадобится специализированный платный инструмент Photoshop.

Да это инструмент, который может решить какую то задачу. Беда в том, что инструмент ничего не гарантирует, в том что -W4 решит ее лишь немногим хуже.

Это неправда.

Если бы было правдой, то у нас не было бы наших уважаемых клиентов. А тем более продлений лицензий.

Зато инструмент гарантированно добавляет работы: надо же разобраться корректно ли его предупреждение в данном конкретном случае, не повлечет ли исправление изменений в логике работы ибо даже здесь в комментах были проблемы двойных ошибок.

У Вас странный подход. Если нет желания исправлять старые ошибки, то анализатор конечно только добавит работы. Если стоит цель сделать код более безглючным, то статический анализ экономит массу времени и денег. Собственно, именно по этому он и нужен. Если подход «х*сь — х*сь и в продакшен», то тут конечно от анализатор один вред. Именно по этому, например, мы не стремимся что-то делать в сторону анализа мобильных приложений и т.п. Там срок жизни проекта несколько месяцев. Мы же ориентируемся на клиентов с большой кодовой базой, которые рады любому способу помогающему повысить контроль над своим кодом.

Кстати, даже если совсем не хочется смотреть на старые ошибки, то тоже нет проблем. Пользу можно получить уже здесь и сейчас. Про это говорилось в начале статьи. Помечаем все предупреждения как неактивные и видим только то, что относится к новому или изменённому коду.

А присвоение в if мне и grep найдет.

И этот человек что-то говорит про ложные срабатывания. Ну-ну… :)
Найти можно, толку то. Будет нереальное количество как ложных срабатываний и наоборот много будет не найдено. Кстати, на эту тему: "Статический анализ и регулярные выражения".
Вы молодцы, да. Но в чем проблема статьи? Вам сказали, что, дескать, было найдено много ошибок, вот они.

Если эти старые ошибки, то, собственно, вот результат их анализа. Если новые, то по свежим следам можно все исправить. А то Вы говорите, что старый код говно, а когда Вам говорят, что ваш новый код потихоньку тоже скатываетесь в это говно, Вы со слюной брюзжите и доказываете, что анализатор говно.

В любом проекте есть ошибки, почему бы их не признать и исправить — вопрос.
Проблема статьи? Наверное в том, что это пиар коммерческого софта на популярном OpenSource проекте, и даже не на одном, а на многих, причем этим даже хвастаются.

Лично я предпочитаю не находить ошибки, я предпочитаю их исправлять. Я больше ценю багрепорт юзера нашедшего ОДИН сценарий при котором чтото упадет. Чем такой вот отчет о том что мы нашли кучу косяков в коде из-за которого «МОЖЕТ» упасть, а может и не упасть, ибо код просто недостижим или вообще заброшен и лежит тут для истории.

Вот если бы автор и компания вместо «Обновляемый список open-source проектов, которые мы проверили с помощью PVS-Studio» вела «Обновляемый список КОММИТОВ и PULL-REQUEST в open-source проекты, которые мы НАШЛИ с помощью PVS-Studio и ИСПРАВИЛИ» или «Обновляемый список open-source проектов в которых наша компания из супер-пупер продвинутых с++ разработчиков выполняет премодерацию патчей» тогда да, вот тогда это громко.

А так — ну да какието проблемы в коде нашли, но «их много — разбираться не будем». Спасибо конечно, но нам то толку мало. Все равно что ходить по улице и орать «вот смотрите тут окурок валяется, и вообще грязно» и звать уборщицу. Окружающим от этого проку то немного будет и чище врядли станет.
Может им за вас ещё и весь мессенджер оставшийся дописать? Человек сделал платной (!) тулзой анализ кода и бесплатно (!) выложил результаты. Да, это пиар. Но пиар, которым вы можете воспользоваться, улучшив качество вашего кода. Не хотите, это уже другой вопрос. Но почему вы считаете, что после анализа, за вас ещё должны ваш код поправить и патч выкатить?

А на то что вам кажется, что подобные ошибки, а это ошибки, мало влияют на суть — ну у нас же всё работает, так это от уж извините, от недальновидности. Каждая такая ошибка — бомба замедленного действия. Ну да, у вас пока что нет ситуации, когда в функцию приходит NULL, ну да у вас адреса 64х-битных указателей не вылазят за младшие адреса. Это всё меняется, это всё проявляет себя. Придёт новый человек и допустит ошибку в вызове, направив NULL. И тогда такая бомба проявит себя. Такие ошибки могут стоить даже дороже потому что на их отладку можно потратить не один рабочий день, когда они закопаны глубоко в легаси-коде.

Я за свой опыт насмотрелся уже проектов, которые просто тонули в проблемах своего легаси. Почему вы не хотите обеспечить себе счастливое будущее проекта, просто поправив ошибки на которые вам уже бесплатно указали, да при этом ещё напрасно хаете человека который для вас это, опять же повторяюсь, бесплатно сделал — решительно непонятно.
Это блог PVS-Studio, они за него деньги платят, это общеизвестный факт. Что хотят, то и пишут в него.

Без обид, но Вы своими высказываниями выносите мне мозг. Тут один абзац лучше другого, я даже не уверен, что нужно вступать в дискуссию.

Вы что-нибудь, например, о undefined behavior слышали? Это когда 100 раз работает нормально, а один раз падает. И все потому, что программист не знает языка, на котором пишет.

PVS-Studio проверили дикое количество проектов (от boost и Qt до PostgreSQL и Source), во всех случаях разрабы были благодарны за проделанную работу. Но Вы прям уникальные парни, я смотрю.
>> Лично я предпочитаю не находить ошибки, я предпочитаю их исправлять. Я больше ценю багрепорт юзера нашедшего ОДИН сценарий при котором чтото упадет. Чем такой вот отчет о том что мы нашли кучу косяков в коде из-за которого «МОЖЕТ» упасть, а может и не упасть, ибо код просто недостижим или вообще заброшен и лежит тут для истории.

Facepalm. И эти люди пишут сетевые клиенты. Которые получают и обрабатывают данные хз откуда. И как они их обрабатывают — мы видим на примере данной статьи.

Вам фраза «удаленное выполнение кода» о чем-нибудь говорит?

Ппц. Судя по продемонстрированному коду, а еще в большей степени — по реакции на него, Миранду использовать нельзя ни в коем случае, потому что вероятность того, что через неё вас удаленно отэксплойтят, резво стремится к единице.
Если магия работает, то это случайность, а если не работает то очевидное поведение. Имено так надо относится к магии.
>> Как вы думаете если у нескольких миллионов пользователей за несколько лет в этом месте ничего не падало, то каковы шансы что этот указатель окажется NULL?

Эти шансы вполне могут оказаться стопроцентными, когда вы, например, обновитесь на новую версию компилятора, которая решит креативно соптимизировать данный кусок кода, поскольку там все равно U.B. gcc этим особо славен, но MSVC тоже иногда может.
I'm afraid this is the worst project in regard to memory and pointers handling issues I've ever seen.


Догадайтесь, на что они обиделись.
Смысл на зеркало пенять? Ну, неприятно, ткнули носом в твои ошибки. Неприятно, да, бывает. Разве это плохо? Станешь чуточку умнее и аккуратнее.
Я-то прекрасно понимаю, но не все. Плюс в англоязычной среде этикет немного другой, эта цитата резче, чем на русском звучит.
Плюс в англоязычной среде этикет немного другой

/me вспоминает пальцы Линуса, его опусы про gcc-4.9 и многое другое.

А не путаете ли вы часом англоязычныую опенсорсную среду с платной поддержкой какого-нибудь RedHat'а, где специально обученные люди ни в коем случае не будут называть недалекого клиента так, как он того заслуживает?
В книге «Русские проблемы в английской речи» Линн Виссон есть глава «Я прав, а ты нет», в которой рассматривается проблема выражения резкой и категоричной критики, когда вроде бы по-русски нормально звучит (хоть и неприятно), а в английской – просто ужасно. Думаю, marapper имел в виду этот момент.
Огромное спасибо за книжку, выглядит интересно.
Нет, это действительно так к сожалению, прямой перевод русского на английский почти всегда звучит почти оскорбительно. Проблема давняя и известная.
Как вы думаете если у нескольких миллионов пользователей за несколько лет в этом месте ничего не падало, то каковы шансы что этот указатель окажется NULL?
Хорошая логика. Важна не вероятность, а то, что это может случиться. Если подушка безопасности не помогает в большинстве аварий, то зачем нужна подушка безопасности… хм?
А откуда Вы знаете, что у пользователей не падает в этом месте? У вас посылаются coredump-ы после каждого падения? Вроде для программ вроде Miranda это не типично.
А откуда Вы знаете, что у пользователей не падает в этом месте? У вас посылаются coredump-ы после каждого падения? Вроде для программ вроде Miranda это не типично.

Поддерживаю, для Miranda ещё надо предварительно, до падения, качать отладочные файлы иначе отчёт сформируется некорректно и не будет принят, что неудобно для многих, а для простых пользователей, которые сидят на релизах эта задача практически нереальна.

Вот пример как в проекте FlylinkDC++ побороли неотлавиваемые и редкие проблемы путём прикручивания стороннего сервиса анализа дампов, это не реклама, это просто часть моего личного опыта.

P.S. и да, я уже не в первый раз выражаю искреннюю благодарность команде PVS-Studio! Благодаря анализатору в FlylinkDC++ удалось найти и исправить кучу мест, в которые уже давно не заглядывали или просто не видели в них ошибок. Однако в этих потаённых местах было много легаси кода, собственно до сих пор всё ещё очень много кода из 90-х, хоть постепенно проект и переписывается на C++11.
UFO just landed and posted this here
UFO just landed and posted this here
Если есть ограничение на параметры — его надо описать явно. Например, конструкцией assert, которая именно для того и нужна.
А контрактное программирование? А защитное программирование? Слышали такое?
То, что сегодня никто не вызывает с dat == nullptr, не значит, что завтра в ваш опенсорс проект не придет некий Вася из 9-го класса, и не вызовет эту функцию с dat == nullptr.
Хотите верьте, хотите нет, но 14!!! лет назад мне было 19 лет и я не только не слышал ни про контрактное ни про защитное программирование, но я и не знал что такое Си а что такое Си++. Что такое объекты, автоуказатели, стандартная библиотека. С трудом понимал разницу между SendMessage и PostMessage. Суррогатный аналог виртуальных таблиц для меня был просто откровением и изящнейшим архитектурным решением.. И с удивлением узнавал что не стоит одновременно менять значения переменных из разных потоков.
Я расстраивался что «Банда четырых» уже изобрела фабрику и другие «мои» изящные решения. :)

Я как раз и был тем «Васей» правда со второго курса который эту функцию вызывал и не с nullptr, а с '1' :)

И кстати на статью я ни грамма не обиделся. Мне уже давно без разницы насколько хорош или плох какой то код как код. Я давно его оцениваю не по минимальному количеству предупреждений статистического анализатора.

Немного грустно от того, что кто-то даже на таком «плохом и ужасном» коде в который я хоть и не много, но вложил своих сил — сделает деньги и не малые. Но это очередной пример того, как даже столь ужасный код можно монетизировать.

На месте автора статьи (конечно бы если бы я преследовал иную цель) этот лог бы я направил прежде всего разработчикам. А уж потом бы пиарился. Даже в этой статье есть отсылки к следующим статьям: «ой а там ваще ужас ужас». А так статья воспринимается как просто наглый пиар на по настоящему открытому и бесплатному софту.

Вот разработчикам Миранды было не слабо выложить в открытый доступ реверс закрытых протоколов, свою реализацию XMPP. Поделиться этой реализацией с QIP (согласиться на нарушение GPL). Разработчикам CLANG тоже не слабо поделиться своими разработками. Вот ни грамма бы не обиделся бы на критику миранды от них или от Беркуса или Момджана. Но тут извините.
UFO just landed and posted this here
> круто, но в проекте аж три таких файла, теперь мне нужно во все заглядывать и искать.

Не нужно никуда заглядывать и ничего искать. Нужно установить и запустить анализатор CppCat. Демонстрационная версия работать неделю с полной функциональность. Этого более чем достаточно для проверки проекта, по крайне мере однократной.

А потом можно и купить CppCat-ов на всю команду. :)
UFO just landed and posted this here
У меня и вижал студия экспресс, оно же не взлетит с ней.
Не касаемо CppCat, а вообще, уже есть Visual Studio Community 2013. Она умеет если не всё, то почти всё что и профессиональная (плагины уж точно).
V595 The 'group->cl.items' pointer was utilized before it was verified against nullptr. Check lines: 137, 139. Miranda clcitems.cpp 137
круто, но в проекте аж три таких файла, теперь мне нужно во все заглядывать и искать.
Тут же:
mir_free(group->cl.items[i]);
поздравляю, вы потратили моё время впустую, mir_free — сама проверяет.
И как она это проверяет, интересно? Значение group->cl.items[i], может быть, она и проверяет — а вот group->cl.items она не может проверить в принципе.

6. V595 The 'opi.odp' pointer was utilized before it was verified against nullptr. Check lines: 894, 897. Miranda profilemanager.cpp 894
mir_free((char*)opi.odp[i].pszTemplate);
mir_free(opi.odp);
мимо.
То же самое.

UFO just landed and posted this here
Диагностика V595 очень проста и как не странно, этим же и удачна. Она работает следующим образом:

Выдать предупреждение, если в начале указатель разыменовывается, а затем проверяется на равенство 0. И всё. Есть некоторые отдельные исключения, но они к делу не относятся.

Диагностика не всегда указывает на ненастоящую ошибку. Иногда, указатель никогда не равен нулю. Но тогда вопрос, зачем нужна такая проверка? Чтобы запутать читающего код? Таким образом, анализатор если выявляет не ошибку, то по крайней мере код, который пахнет. Часто его можно упростить или улучшить. Например, если функция всегда принимает только ненулевой указатель, то возможно его стоит заменить на ссылку.
2. Оно ругается на вот это: opi.odp[i]
Насколько я понял, там примерно следующая ситуация: есть переменная size — размер массива, и есть ptr — указатель на первый элемент массива (названия условные). Если size == 0, то ptr — нулевой указатель, если size > 0, то ptr указывает на первый элемент массива длины size. Сначала они бегут по элементам массива от 0 до size – 1 (если указатель равен 0, то и size равен 0, а следовательно тело цикла не выполняется ни разу), а потом вместо проверки if (size > 0) используют совершенно равнозначную ей (при соблюдении вышеописанного инварианта) проверку if (ptr). В принципе ничего такого криминального.
Разумеется, ничего криминального. Только вот если писать один и тот же код в 100 разных местах — то пару раз напишется что-то другое. Кто проверит, что работа с этими структурами всегда выполняется корректно?

PS Так и хочется написать что-то вроде assert((size == 0) == (ptr == nullptr))
PPS А еще сильнее хочется переписать, используя векторы и умные указатели
PS Так и хочется написать что-то вроде assert((size == 0) == (ptr == nullptr))

Сомневаюсь, что PVS-студия достаточно умная, чтобы понять такой намёк.
Зато программист, увидев такой код (ассерт), сразу пометит строку с диагностированной проблемой как ложное срабатывание и, не вглядываясь в остальной код, пойдёт дальше.
UFO just landed and posted this here
В одной из свежих. Не вижу смысла в таком подходе. Нужно установить анализатор и воспользоваться им.
UFO just landed and posted this here
Методология статического анализа подразумевает некоторый процент ложных срабатываний. С ними можно и нужно бороться. И разработчики статических анализаторов ведут эту невидимую борьбу. Тем не менее статический анализ, это не искусственный интеллект и задача инструмента выделить места кода для последующего изучения программистом.
По опыту использования PVS-Studio в 2009-2010 году могу сказать, что для того, чтобы найти одну реальную ошибку нужно было пролопатить сотни, если не тысячу предупреждений ни о чём. Это же кстати относится и к статическому анализатору VS2013 и Coverity 6. Вам об этом разработчики и пытаются сказать, возможно слишком резким тоном. Вы им: «да ваш год отстой, 80% указателей не проверяются перед использованием», а они вам «да ваш статический анализатор отстой, у вас 80% предупреждений ни о чём». Чтобы зря друг на друга не наезжать и не переливать воду в ступе, разработчикам Miranda NG нужно было бы написать статью «PVS-Studio получает приз «чемпион по ложным срабатываниям»», но вам за статьи деньги платят, а Miranda NG это чистый энтузиазм, поэтому такая статья врядли появится.

Единственный вариант использования статических анализаторов, который я вижу — это подключить их к CI и в обязательном порядке просматривать новые предупреждения. Их будет не очень много и с ними можно будет справиться. Починить же тысячи предупреждений (большинство из которых false positive) в проекте с многолетней историей по-моему не представляется возможным.
Есть смысл посмотреть на актуальную версию PVS-Studio и не смотреть на 64-битные диагностики. Результат будет намного лучше.
Скачал свежий триал. Поставил. PVS-Studio->Check Current File.

В окошке где должны быть результаты
License information is incorrect. Please check your registration data or contact Customer Support at support@viva64.com 1

И красным по черному окну Clicks remaining: 18 (can be extended). Это я видимо уже дважды кликнул по надписи о некорректной лицензии.
Отпишите, пожалуйста, в почту — подскажем что не так.
А, разобрался, у меня была в настройках вбита лицензия ещё с 2009 года. Вытер и лицензия стала Trial.

Проверил несколько файлов, отключил 64-битные предупреждения, оставил только GA:
Туча предупреждений на код в файлах c:\Windows Kits\Include\shared\minwindef.h, c:\Windows Kits\Include\um\winnt.h, winuser.h, shellapi.h и пр.
V677 Custom declaration of a standard 'SHORT' type. The system header file should be used: #include <WinNT.h>. winnt.h 344
Исключил весь C:\Windows Kits, не ясно только, почему он не исключен по умолчанию.

V668 There is no sense in testing the 'task' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error.
В классе определен operator new, который возвращает NULL при неудаче.

V668 There is no sense in testing the 'newPointee' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error.
В шаблонной функции вызывается newPointee = new T();, где T — параметр шаблона. Откуда уверенность, что в T не перегружен operator new?

V512 A call of the 'memcmp' function will lead to underflow of the buffer '& OpPattern'.
V512 A call of the 'memcmp' function will lead to underflow of the buffer '& maxSupportedOpPattern'.
Анализатор решил, что программист должен сравнивать структуры полностью, а в коде сравниваются только первые 12 байт «префикса».

V571 Recurring check. The 'if (((HRESULT)(hr)) >= 0)' condition was already verified in line 2124.
Ну как бы да, лишняя вложенная проверка. Но это никак не влияет на работоспособность кода.

V580 An odd explicit type casting: (void * *) & pInterface. Consider verifying it.
Типичный каст для COM. Проверифаить все вызовы QueryInterface не представляется возможным.

Ну что я о плохом да о плохом:
Нашел одну ошибку типа
V519 The variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 7195, 7196.
Другое дело, что это скорее всего где-то дальше в коде обрулено, но всё равно надо починить.

V690 The 'Class' class implements the '=' operator, but lacks a copy constructor. It is dangerous to use such a class.
Эти предупреждения тоже стоит изучить детальнее.

Но в общем и целом мало что изменилось — реальных ошибок очень мало и их очень тяжело выискивать среди десятков и сотен приведеных выше false positiveов. В общем, как я уже писал выше — добавлять в CI и чинить/глушить новые предупреждения. Времени на починку 1000 подобных предупреждений, из которых менее 1% валидны никто не даст.
И красным по черному окну Clicks remaining: 18 (can be extended). Это я видимо уже дважды кликнул по надписи о некорректной лицензии.
Не ошибка ли, что засчитываются щелчки по сообщениям, не приводящие к переходу в код?
Но раз уж такой придирчивый то почему он пропустил:
MenuItemOptData *iod = (MenuItemOptData*)tvi.lParam;
if (iod->pimi) {

Ну а что тут не так? iod после этого на nullptr не проверяется — такой ворнинг и не генерируется.

Позвольте еще и за имена переменных поругать: что за iod, pimi, pimo?
Почему часть локальных переменных в camelCase, а часть в PascalCase?
UFO just landed and posted this here
Так PVS не ругается, если указатель просто не проверен на nullptr перед использованием. Может вы и вправду уверены, что он никогда не равен nullptr.
Но согласитесь, подозрительно, что указатель сначала использовали, а потом проверили. Т.е. вроде как программист не уверен, что указатель не null, раз проверка есть, но при этом он его до этого использует без проверок.
UFO just landed and posted this here
kosmos89 прав, прислушайтесь к нему, такой код надо переписывать. Если остаются сомнения переставляйте проверку выше, заменив её ассертом. Если же там всегда валидный указатель, то убирайте странную проверку постфактум. Убрать проверку необходимо поскольку она может скрывать за собой проблему, к примеру, уже не работающую логику, зависящую от этой проверки. Просто задумайтесь вот над чем: код имеет очень долгосрочную поддержку, уже много раз переписывался. Теперь представьте ситуацию: раньше там было значение его проверяли на неравенство нулю, а потом провели оптимизацию потребления памяти или изменили логику работы с объектом и заменили значение на указатель, а логику исправить забыли. В общем, это очень серьёзная проблема, такого «подозрительного» кода просто не должно быть в проекте поскольку он затуманивает восприятие и не позволяет видеть похожие проблемы в других местах как во время рефакторинга, так и в процессе написания нового кода.
Если вы хотите что-то максимально полезное вынести — начните не с нулевых указателей, а с некорректного использования sizeof/SIZEOF, и прочих багов с подсчетом кол-ва элементов.
сейчас, по прошествии ~10 лет могу только себе представить, что бы выдал анализатор на history++ :)
но, дельфи оно не умеет.
Какая разница, если в итоге он отлично работал. Спасибо Вам за этот плагин :)
Занятно. В обсуждении поста на Reddit появился /u/FigBug, который начал проект Miranda IM. Никакой желчи, никаких упрёков и обид в сторону анализатора. Признался, что качество кода было не очень:
Скрытый текст
I must apologize for Miranda, even though there is probably none of my code left, I set the tone and style for the project.

I had no idea what I was doing when I started the project and I never thought it would get as popular as it did and be around for 14+ years.

I had less than 2 months Windows programming experience when I started the project. I used C and not C++ because I couldn't figure out how to get a C++ WinProc to compile. The entire point of the project was to hook a chat bot to ICQ to harass my friends. There was no 'design' or 'architecture'. I had no idea how to run an open source project so I just let anybody commit whatever they wanted and then I got bored of it and let the project run on auto pilot until others took it over.

Sad thing is, the worst code I've ever written is by far the most popular thing I have ever created.
Вот это я понимаю. Очень жизненно. «Слова не отрока, но мужа». Насчет самого ужасного творения, которое стало самым популярным, я его очень хорошо понимаю. Хотя даже самым ужасным моим творениям очень далеко до популярности Миранды )
Ого! Попкорн при прочтении комментариев очень пригодился, давно такого не было на хабре, спасибо!
UFO just landed and posted this here
Не обещаю, но можно попробовать. Напишите нам на почту.
UFO just landed and posted this here
Да давненько не было…

Повторюсь есть некое непонимание: Миранда, которая официальная, это в первую очередь ядро. Кстати вот туда комитить просто так мне бы совесть бы не позволила. Да и был там один разработчик который любил своими комитами билд ломать… даже не собирая. Оно относительно стабильно и неплохо.

А вот модули разрабатывали кто во что горазд мой еще тесно связан с ядром — приходилось подстраиваться. А многие так вообще. И жили они кто где, на разных репозитариях, процентов 70 откровенно заброшенных, но тем не менее популярных. И то что их разработчики просто не хотели больше поддерживать свой модуль откровенно мешало разработке ядра.
К примеру 30% пользователей используют модуль clist_modern, а с новым релизом ядра ломается совместимость и модуль перестает работать. Причем модуль просто по незнанию использовал какой то глюк в интерфейсе взаимодействии и его хотели починить. Делов то поправить пару строк… Но я этим заниматься не хочу — потерял интерес. И что делать разработчикам ядра?
Вот и старались стащить все в одно место, чтобы хоть как то контролировать и приглядывать за разработкой хотябы популярных модулей.
Я не могу воспринимать того человека как программиста после вот этого высказывания:
программа, которая может выдавать сообщения типа
> V303 The function 'lstrlen' is deprecated in the Win64 system. It is safer to use the 'strlen' function.
вообще не заслуживает ни доверия, ни того, чтобы на нее даже толком смотреть.
UFO just landed and posted this here
Зато там указан возвращаемый тип, который int. Следовательно, эта функция не работает со строками длиннее 2 Гб.

Если вы мне возразите, что в Миранде не бывает таких длинных строк — я соглашусь. Но нельзя говорить про все программы на примере одной только Миранды. Может, кто-то перешел на 64 бита исключительно из-за длинных строк? Тогда эта диагностика окажется для него очень даже полезна. А значит, в синтаксическом анализаторе, выросшем из проекта Viva64 — ей самое место.

Если же именно вам именно в Миранде больше нравится использовать lstrlen — то эту диагностику можно выключить.
UFO just landed and posted this here
Выбрали неудачную функцию для обсуждения. Я понимаю, что всячески хочется показать никчёмность анализатора, но это неконструктивный путь.

64-битные диагностики по своей сути дают много ложных срабатываний и с этим ничего нельзя сделать. Именно поэтому мы не включили их в CppCat. Программисты не подумав включают всё на максимум, а потом жалуются, что много ложных срабатываний. Мы вообще со временем думаем спрятать 64-битные диагностики подальше от шаловливых рук. :)

Полный набор 64-битных диагностик нужен только тем, кто создаёт ресурсоёмкие приложения, потребляющие большой объём памяти и обрабатывающий большие массивы. Если больших массивов нет, но всё-таки хочется использовать 64-битные диагностики, то можно ограничиться подмножеством. Например, можно выключить все 64-битные предупреждения кроме V114, V204, V205, V220, V301. Но возможно, что-то захочет просмотреть и V112. Тут всем не угодишь, поэтому мы не выделяем какое-то подмножество.

Такое подмножество можно выбрать самостоятельно, отключая неинтересные диагностики. Это делается очень просто. Можно использовать настройки или зайти в контекстное меню (правый клик мыши на сообщении).

А по поводу lstrlen(). Она устарела с точки 64-битности, ибо не вернёт правильное значение, если длина строки превысит INT_MAX символов. Понятно, что это что-то необычное. Но раз это 64-битная программа, то теоретически это возможно. А нулевые указатели тут вообще ни при чём. Это не забота 64-битных диагностик. Они говорят о своём специфическом.
UFO just landed and posted this here
«В .NET я не хочу разбираться, я обижен на МС за то что закопали мой любимый Visual Basic.»

Это многое объясняет.
UFO just landed and posted this here
Что означает «закопали живьем»? Больше нельзя писать скрипты .vbs? Больше нельзя писать макросы на VBA? VB.NET — это не язык программирования?
UFO just landed and posted this here
А что мешает им продолжать работать?
Больше нет компилятора VB, выпускающего native код, как я понимаю. Последний — VB6 98го года.
Было бы интересно попробовать установить Visual Studio 98 на Windows 8.1
Угу, учитывая, что при установке надо было иметь, емнип, IE4.0 и что-то с SP4 для W2K.
Даже в XP SP3 запустить проблемно. За прошедшие 16 лет все ушло вперед, начиная от библиотек-компонентов, и заканчивая оптимизацией под новые процессоры.
А так-то что — вполне можно MSVC 2.0 поставить и клепать на нем программы. Никто не мешает.
Кстати автор уже дважды пиариться на одном коде. В 2011 году же была серия статей по анализу кода миранды. Я даже ради комментов к этим статьям зарегистрировался тут.

Andrey2008, вы действительно расчитывали, что в OpenSource проекте с более чем 14 летним кодом, с максимум десятком активных разработчиков к настоящему моменту, с отсутствием «правильных» подходов к процессу разработки ваш анализатор найдет что то новое?

Кстати новая статья намного хуже. Первый цикл все таки выглядел как «давайте я научу вас как не стоит писать код», «избегайте популярных косяков». Та статья действительно учила и лишь немного выглядела рекламой (такая скрытая и ненавязчивая «Выставляйте высокий уровень предупреждений у компилятора и используйте статические анализаторы» в шестом и последнем разделе статьи).

Новая же «глядите как наш анализатор умеет клево находить очевидные косяки» часть из которых явно наследие копипасты, а уж вещи типа new[] / delete / free c головой выдают начинающих программеров, увы я не поверю что кто то может как вы сказали «забыть» квадратные скобки у delete или случайно использовать free. Вы бы хоть объяснили почему так не надо делать.

P.S. Кстати удивлен отсутствием пиара фичи «мы можем находить оператор присвоения в условиях под if»
Статьи бывают очень разные. Поскольку в этот раз было слишком много предупреждений я решил говорить только о них, не рассматривая рекомендации. Иначе вообще слишком длинно получится. По поводу «оператор присвоения в условиях под if» — это будет во второй части. Скоро опубликую. Жду перевода на английский язык.
Ух, какое мясо-то! Давненько такого не было, спасибо!
Sign up to leave a comment.