Комментарии 33
В патче первого дня поправят! /s
if (strlen(text) > sizeof(text))
Sys_Error("memory overwrite in Sys_Printf");
Кстати, для таких случаев существует функция strnlen().
Остаётся с Вами только согласиться, но, кстати, не факт, что она тогда у них была. Первый Квейк вышел в 96ом, а как минимум этот ман указывает на то, что strnlen
был описан только в POSIX.1-2008, в то время как более прямолинейная её сестра имеет больший послужной список -- POSIX.1-2001, C89, SVr4, 4.3BSD
.
а разве выражение не должно быть таким:
if (strlen(text) >= sizeof(text))
Нет, последним элементом си-строки является null-терминатор. Функция strlen его не считает. Таким образом длина строки всегда на 1 элемент (char) меньше, чем размер массива, необходимый для её размещения в памяти.
UPD: сорян, вопрос-то правомерный. Эт я тупанул.
Так, ну длинна массива -- 2048 байт, стало быть максимально валидное в этом случае значение, возвращаемое strlen
-- 2047 (без учёта нуль терминатора в конце Си-строки). Стало быть, оператор >=
выглядит логичнее, так как 2048 -- некорректная длинна строки. Другое дело, что навряд бы это могло исправить сложившуюся ситуацию.
Прошу прощения что не в тему. Но художник третьей картинки пробовал сам так подмигнуть поджав рот в другую сторону от закрытого глаза?)
Так, провёл натурные испытания. Про подмигнуть не знаю, но если сначала закрыть (и удерживать) глаз, то потом можно поджать рот с любой стороны. Т.е. картинка реальная, даже без использования хирургии.
Возможно не у всех. Проверил: у меня или глаз открывается, или уголок не поджимается.
Вношу лепту -- сначала пришлось закрывать глаз и отводить уголок рукой. Через пять минут изнуряющих тренировок результат был достигнут -- рожа строится что надо.
ЗЫ -- комментарий не является медицинской рекомендацией, последствия для здоровья неизвестны.
Фрагмент 12
for (p = newname; (*p == ' ' || *p == '\r' || *p == '\n') && *p; p++)
Насколько я понимаю, тут выполняется поиск разделителя до конца строки. В конце строки *p будет равно 0, что сгенерирует false и выход из цикла. Похоже, что анализатор тут неправ.
Так то лучше было бы проверять *p != 0 в начале выражения, но это уже другой вопрос все-таки.
Если *p == 0
, то выражение в скобках тоже false, поэтому условие && *p
даже проверяться не будет.
Если смотреть на куски приведенного кода "в статике", то ваш анализатор прав на все 100%. Но, код постоянно перетерпевал изменения, отсюда и образовались такие несуразицы - программисту было либо лень, либо некогда анализировать код до конца при внесении мелких изменений. То же самое касается констант и сравнений с ними - просто подгоняли значения по ходу. О чем все это говорит ? О том, что нужно устраивать регулярный рефакторинг году, но на это не у всех есть время, силы и желание.
Я точно видел у Дяди Боба в книжке картинку с графиком затрат на поимку одного и того же условного бага на разных стадиях софта. Утверждается, что поимка до релиза много дешевле, чем после. Если есть возможность встроить какие-то тулзы в общий цикл разработки приложения (не обязательно даже статический анализ и, строго говоря, не обязательно наш), то шансы не допустить указанные Вами случаи увеличиваются кратно и трудозатраты на это, наоборот, снижаются.
Тут надо сделать поправку на то, что QW был написан и зарелизен лет 15 до того как The Clean Coder увидела свет.
Если правильно понимаю, то в те времена заместо чистого кода и архитектурных принципов в целом (в плюсах) пользовались методом Бутча (я понимаю, что QW не на плюсах написан).
Я бы так сказал -- мне, как человеку, который на момент релиза этого проекта писал разве что каракули на бумаге, приятно осознавать, что у меня сейчас есть энное количество методов сделать себе жизнь легче. В конце-концов, если в таком великом проекте есть, казалось бы, такие очевидные огрехи, то мне расслабляться точно нельзя =)
Вообще, геймдев -- зверь специфический. Раз заговорили о чистом коде -- можно найти некоторые мнения и против этой методологии. Думается, что если бы Кармак прятал код за тысячей интерфейсов, в кваку бы мы так и не поиграли =) Но это, как говорится, совсем другая история.
Скажите, пожалуйста, вам не кажется, что полсотни комментариев // PVS-Studio:
в одной статье — это как-то слегка перебор? Это у вас KPI для технических писателей такое?
Не думал при написании, что это так бросится в глаза -- видимо, думал не туда. Идея оформления авторская, требований к минимальному кол-ву упоминаний у нас нет, так что виноват, стало быть, тоже автор, то есть я =) Мне хотелось отделить наши комментарии от комментариев в исходниках. В следующей статье подумаю над чем-нибудь менее бросающимся в глаза, как минимум в заголовках вырезок.
В следующей статье подумаю над чем-нибудь менее бросающимся в глаза
Как насчёт такого?
// Файл: client/model.c
// Функция: void Mod_LoadTexinfo (lump_t *l)
Или же, если проверяемый проект есть на гитхабе, рядом с фрагментом кода давать прямую ссылку на релевантную строчку в коде.
Мне кажется, что молодого человека заставили написать статью на хабр. В следующий раз будет код Elite через PVS разгребать. Что не отменяет того, что утилита супер.
мы с удовольствием приглашаем вас поспорить в комментариях о Descent
Некоторых моих знакомых от него тошнило. В том смысле, что укачивало.
Но и Descent был далеко не первым. Была, например, "Frontier: Elite II" - от неё, кстати, кажется, сырцы утекали, но там в принципе баг на баге был. Была ровесница Descent'a игра "Terminal velocity".
Натыкался на преинтереснейшую статью с разбором Фронтира (http://watsonmw.com/fintro/), но там автор сам дисассемблировал.
Сам я в Descent не играл, да и не большой фанат более классических "леталок", но встречал упоминания об укачиваниях, отчего появился вопрос -- почему в ней? Если правильно понимаю, в той же "Элитке" были 6 степеней свободы, но такого эффекта (по артефактам в интернете) не наблюдалось.
В Descent коридоры, в которых ответвления могут быть не только вправо-влево, но и вверх и вниз, причём после такого поворота верх и низ меняет направление. Плюс сами движения корабля игрока "инертные" и "качающиеся". При этом надо достаточно быстро лететь и ориентироваться в 3d лабиринте (и, конечно, стрелять).
В играх с открытым космосом (Elite/X и т.п.) обычно нет лабиринта, а в бою ориентируешься так как удобнее (отчасти по "радару", отчасти по ключевым объектам, которых немного).
Получается, мозг игрока в прямом смысле думает, что его носитель катится кувырком из-за крутящегося окружения. Коридоры там ещё очень узкие, вероятно тоже сказывается на заметности движения окружения.
Полагаю - тут всё гораздо глубже. Видимо - люди по типу мышления делятся, условно, на 2D и 3D.
В своё время игра мне очень нравилась, и я пытался привлечь в неё массу народа - знакомых, родственников и сокурсников. В итоге оказалось, что часть в принципе не могли в неё играть - их укачивало, а даже если укачивание было не сильным или через какое-то время проходило - такой игрок всё равно в каждом лабиринте искал "верх" и "низ", ориентируя корабль по светильникам на "потолке", например, и его очень обескураживало, если светильники вдруг за поворотом "переползали" на стену или даже начинали встречаться сразу на двух поверхностях. Кроме того - такие игроки использовали (как в DOOM'е) повороты влево-вправо и стрейф вбок и вверх/вниз, но никогда не маневрировали носом корабля вверх-вниз в полёте (только стоя на месте, чтобы "выровнять" корабль по "полу"). Спиралевидные коридоры и карта к ним, которую надо было умудриться прочитать, были ещё одной причиной, по которой игрок бросал игру.
Но была и часть игроков, которая сразу же начинала использовать всё возможности кораблика, закладывая абсолютно любы виражи, "штопоры" и "петли". В сетевой игре это было особенно заметно - такие игроки имели громадное преимущество.
По аналогии с тем же DOOM'ом - это как представить одного игрока, умеющего стрейфиться и бегающего вокруг противника, а второго - который освоил лишь стрелочки, и чаще всего бежит либо вперёд, либо назад.
Так что я не думаю, что "мозг игрока думает, что тот катится кувырком", скорее - дано или не дано. Не все могут быть лётчиками. :)
Ква! Как писали код во времена Quake