Pull to refresh

Comments 43

int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23

На самом деле, в этой строке, судя по комментарию, две ошибки :)
Видимо да. Кстати, это не единственно место с неудачным оператором &&. Вот этот пример в статью не вошёл, но он тоже прекрасен:

#define WAVE_FORMAT_1M08       0x00000001       /* 11.025 kHz, Mono,   8-bit  */
#define WAVE_FORMAT_1S08       0x00000002       /* 11.025 kHz, Stereo, 8-bit  */
... и так далее

void QAudioDeviceInfoInternal::updateLists()
{
  ...
  DWORD fmt;
  ...
  if((fmt && WAVE_FORMAT_1M08)
     || (fmt && WAVE_FORMAT_1S08)
     || (fmt && WAVE_FORMAT_2M08)
     || (fmt && WAVE_FORMAT_2S08)
     || (fmt && WAVE_FORMAT_4M08)
     || (fmt && WAVE_FORMAT_4S08)
  #ifndef Q_OS_WINCE
     || (fmt && WAVE_FORMAT_48M08)
     || (fmt && WAVE_FORMAT_48S08)
     || (fmt && WAVE_FORMAT_96M08)
     || (fmt && WAVE_FORMAT_96S08)
  #endif
  )
  ...
}

А можно узнать, были ли разработчики Qt уведомлены о найденных ошибках?
Нет. Я имею на руках здоровенный отчет, который нужно внимательно исследовать. Я отправлю разработчикам QT ссылку на перевод этой статьи, когда он появится. Если их заинтересует эта заметка, они сами смогут проверить библиотеку и исправить то, что посчитают дефектами.
Ну не то чтобы прямо сама собой ^_^.
Спасибо. :)
Но с моей точки зрения — именно, само собой.
> Как уменьшить вероятность ошибки на этапе написания кода

Не юзать сраный Си++)
Прям тролль:) Судя по вашему профилю, вам нравится C и Перл. А что с С++? Откудо такая ненависть не смогли переучиться, классов боитесь? По собственному опыту, на Перле можно куда круче накосячить.
Есть довольно дорогой способ проверки качества кода — заставлять одного (лучше более опытного, но не обязательно) программиста смотреть правки другого и давать замечания. Для того, чтобы замечания были обоснованными — также необходимо наличие некоторого корпоративного свода правил кодирования.
Да, слишком дорого. Поэтому и появился компромисс — статические анализаторы исходного кода. Ими может воспользоваться сам программист. А может и тот, кто просматривает чужой код. Он экономит своё время, читая не весь код коллег, а только наиболее подозрительные места.
P.S. Просто так, не в тему. Порадовал юмор разработчиков QT. Им было нужно какое-то магическое значение указателя для внутренних нужд. Они выбрали это:
notified.insert( (void*)dns, (void*)42 );

Про таблицы не согласен, затем плодить лишние массивы, если можно красиво все оформить через switch? Главное, чтобы в нем условия были отсортированы, а не шли вперемешку.
Таблицы еще и оверхед вносят, хотя если свитч грозится быть более, чем из 10 элементов, то лучше табличку сделать, а там поиск по ключам оптимизировать, то есть упорядочить их и юзать бинарный поиск вместо линейного как в свичах.
Вспоминаются исходники LastFM, файл SideBarView.cpp, где длиннющий метод с множеством case-ов.
Ищится по:
//TODO Woah! This became huge. DRY!
//REFACTOR IMMEDIATELY!
И, кстати, не факт, что так будет быстрее. Если разные ветви выполняются с разной частотой, то бинарный поиск может оказаться хуже, чем если наиболее часто используемые проверить сначала, а потом всё остальное. Но тут подводный камешек, что C++ может переставить порядок по своему усмотрению.
Да, согласен. Часто это тоже будет хорошим вариантом. Впрочем от забытых break; это не спасает. Надо было ведь такой синтаксис придумать для switch…
Да, break — это неудобно. Зато иногда требуется несколько веток исполнять сразу, и отсутствие break приходит на помощь.
Длинный-предлинный switch(). И, естественно, имеется забытый оператор «break».


Lookup table (BTW, откуда термин «табличный метод»?) я тоже люблю. Но потерянные break ИМХО больше от неумения писать на C++. Потому как эталонный switch выглядит вот так:
switch( condition )
{
break; case 1:
  Foo();
break; case 2:
  Bar();
break; case 3:
  Baz();
break; default:
  ENSURE( false );
}


Ну а те кто честно ручками ставят break после каждого case и так же ручками его там зыбывают… Каждый сам кузнец своего счастья, не?
В книге Code Complete таблицы называются Direct Access Tables (18.2.) и Indexed Access Tables (18.3.) Общим названием для них Стив использует lookup-tables. Наверное название «табличный метод» растёт оттуда.
Вот за что люблю русские переводы :(.
Не знал о таком приеме.
Ситуация точно такая же, как с if (0 == x) — надежно, но неестественно смотрится :)
Ну мы чай не философы на художественной выставке. Естественно смотрится, неестественно смотрится… Код вообще такая штука, которая не очень естественно смотрится :). Главное — чтобы задачи решались и метрики соблюдались. А что школьникам непонятно будет — так на то они и школьники. Деятельность физиков-ядерщиков или микробиологов им тоже непонятна. ИМХО, образование отдельно, промышленное применение — отдельно.
Есть и другое мнение — «программы пишут не для компьютеров, а для людей» :)

Компилятор-то код худо-бедно сожрет, а вот если творение предыдущего программиста без поллитры не поймешь, то печально… Я как-то переписал большой кусок кода на C# только потому, что он был написан в паскалевских традициях и развивать его было мучительно. Впрочем, этот кусок от переписывания сократился раза в два и чуток ускорился.
Давайте будем честны друг с другом. Этот код, так же как if( literal == variable ) замечательно читается :)
Надо бы упомянуть о «несправедливости». Не знаю, правда, как компилятор VisualC++, а GCC/G++ давно умеет сворачивать switch в табличку, если это целесообразно. Конечно, табличка предполагает последовательные значения — ибо просто массив адресов, без ключей. Но для большинства enum'ов — как раз тоЮ что надо.
Пример с «if (q && (q->getQueryName() != _T(»BooleanQuery")" не очень убедителен, так как не очень понятно, что за сущность «q», что возвращает getQueryName и нет ли в округе каких-нибудь перегруженных операторов, меняющих явно видимую логику.
Хотя, простите, ступил — определение getQueryName написано в начале.
А вот расскажите мне, я удивляюсь и не понимаю, как с такими ошибками (функция equals явно что-то часто сравнивает, неинициализированные переменные, неправильная функция декодирования какого-то сообщения и т.д.) это вообще работает, почему?)) И ведь эта библиотека используется во множестве проектов.
Я сам в шоке! :)
Причем в постоянном. Вот представьте, добавляю новое правило, что нет смысла в сравнениях вида if (pointer != «ABCD»). Кажется, что и не найдется то ничего. Разве только лабы у студентов проверять. А оно как полезет в разных проектах из разных щелей… Волосы дыбом. Ну что-то в таком духе:
#define MP4_AUDIO_TRACK_TYPE    "soun"
#define MP4_VIDEO_TRACK_TYPE    "vide"
...
const char* normType = MP4Track::NormalizeTrackType(type);
...
if (normType == MP4_AUDIO_TRACK_TYPE) {
  if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
    continue;
  }
} else if (normType == MP4_VIDEO_TRACK_TYPE) {
  if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
    continue;
  }
} 

Такой код может, кстати, и иметь смысл. Если функция NormalizeTrackType описана в этом же модуле и возвращает строковый литерал, то указатели будут совпадать.
Все очень просто. Есть часто используеме модули и ветки кода. А есть редкоиспользуемы. Видимо, это ошибки в крайне редко используемой функциональности. Или вообще в коде, который не используется но остался «со старых времен». Плюс ряд ошибок программа может «проглотить» — тоесть если, условно, алгоритм выбора оптимального кодека работает неверно — кодек все равно будет выбран. Просто не тот :).
Прочитал про табличные функции. Не знал что это так называется, но сам давным-давно к этому пришел.
такое ощущение, что почти все ошибки в цпп — следствие невнимательного копипаста…
Что намекает на то, что при использовании C++ приходится писать много кода, и очень велик соблазн скопировать кусочек. Если бы не микроконтроллеры, я бы уже давно перестал писать на C++ (:
Скажите, как вы натравили PVS-Studio на исходники Qt? Когда-то выходила бесплатная редакция PVS-Studio, хотел с ней такое попробовать, но не вышло, т.к. Qt генерит какие-то кривые солюшены Visual Studio для своих исходников…
Мы развиваемся :-). И правим-правим-правим недоработки.
как-то совсем «детские» ошибки. после этого немного страшню юзать Qt
Only those users with full accounts are able to leave comments. Log in, please.