Как стать автором
Обновить

Комментарии 121

Андрей, а будет ли сравнение с R#? Понимаю, на данном этапе разработки (как вы говорите это даже не beta) может быть неуместным. Но к моменту релиза такое сравнение — must have.
Сравнения точно не будет, мы зареклись делать любые сравнения. Уверен, что Андрей разовьет эту мысль подробнее. Но смысл в том, что даже когда мы тратим месяц работы команды на подготовку самого объективного сравнения с каким-то инструментом, первый комментарий будет: «Да вы дураки и конечно сделали так, чтобы у вас было лучше!».
Нет, не будет. Я зарекся делать сравнения. Почему — напишу отдельную статью. В двух словах: это крайне трудоемко и при этом все равно никто не верит, так как сравнение не является независимым.

Используете R#? Отлично! Теперь запустите PVS-Studio и найдите ошибки. :)
Даже сейчас R# поможет в первом случае, частично в четвертом (подсветит серым неюзаный аргумент), но не в третьем. Так что кое-какие мелочи все-равно останутся.
Можно ли прикрутить PVS к TFS? В билд-процессы, или в RM?
Даже сейчас R# поможет в первом случае, частично в четвертом (подсветит серым неюзаный аргумент), но не в третьем.

Вы про вот это?

  if (mc_a.Location.File != mc_a.Location.File)
    return mc_b;
Да, проверил, R# предложит упростить до true.
Более того, даже
Random r = new Random();
            if (r.Next(2) == r.Next(2))
            {
                // Logic here
            }

R# предложит заменить на
if(true){// Logic here}
На третий фрагмент мой решарпер говорит «Similar expressions comparison». Версия 9.2.
Для интеграции анализа C# кода в Continuous Integration / Build Automation и т.п. системы, вы можете использовать Command line анализатор напрямую. Подробная документация доступна тут.
Всякие unused arg in string.Format, pure function call, var assigned to self, possible NRE и прочее решарпер найдёт в большинстве случаев. Сложные паттерны с похожими ветками, неполные перечисления в switch и прочее — вряд ли. Надо тестировать. В любом случае у PVS, судя по статьям, очень хороший поиск кривой копипасты, а решарпер такое ловит плохо.
Строго говоря, большинство примеров, приведенных тут, R# покрывает как проверками, так и контекстными действиями и фиксами для быстрой коррекции.
50000 строк. Всего два ворнинга на тему «It is odd that the body of 'Foo1' function is fully equivalent to the body of 'Foo2' function (344, line 356)». Так не интересно.
А сообщения по делу?

По делу, конечно. Но про эти одинаковые функции я знал. А вот в c++ на ~40000 строк PVS-Studio нашел у меня полтора десятка ошибок, среди них были очень серьезные мои косяки.
В С# несколько сложнее выстрелить себе в ногу, чем в С++
Так в C++ анализаторе на порядок больше диагностик. А C# анализатор пока ещё маленький. Но не волнуйтесь, мы его усиленно кормим.
Насколько я понял из статьи, вы пока мигрируете самые простые проверки. Вы дублируете проверки R#, или выделяете уникальные проверки? Можно ли будет разделить проверки на «дублирующие» и «оригинальные», и отключить все проверки одной группы?
Мы не дублируем проверки R#. А если и дублируем, но не специально, а просто как следствие развитие анализатора. Делить мы ничего не будем, так как вообще не понятно зачем это нужно. Ну дублируется какая-то проверка, зачем её отключать? Более того, уверен многие проверки будут более мощные чем у R#, хотя на первый взгляд они будут выглядеть одинаково.
Делить мы ничего не будем, так как вообще не понятно зачем это нужно.

Скорость создания. Продукт с уникальными проверками создается быстрее, чем с уникальными и дублирующимися. Плюс, сразу исчезают сомнения вроде «а нафиг мне PVS, если 90% его функционала так или иначе покрывается R#?»

Сейчас нет возможности проверить (чуть выше я уже ошибся), но почти все проверки в статье (сомневаюсь насчет enum-ов) так или иначе покрываются R# (как минимум, R# привлекает внимание к проблемным местам).
В статье имелось в виду, что мы мигрируем для C# самые простые General Analysis проверки C++ версии PVS-Studio, у нас нет в планах дублировать проверки каких-либо других анализаторов. Безусловно, неизбежно пересечение наших диагностик и диагностик других анализаторов, но это не означает, что они идентичны.
  if (!(hintType.Kind == TypeKind.Interface &&
        hintType.Kind != TypeKind.Array)) {
А ваш анализатор для всех свойств такую проверку делает, или только для специально отобранных?
Не для всех. Есть специальная логика, определяющая, стоит проверять или нет.
Рискну предположить, что правильной будет следующая строка форматирования:

String.Format ("[Line {0}:{{1},{2}}-{{3},{4}}:{5}]",
               File, Row, Column, EndRow, EndColumn, Offset);


Не будет. Потому что {{ — это экранированный знак {. Чтобы вывести первый параметр после символа { — надо написать {{{1}. С закрывающей скобкой еще хуже: Если написать {1}}} — то символ } окажется внутри пары скобок, а не снаружи, что приведет к ошибке форматирования. Тут приходится выносить этот символ в параметры, правильный вызов выглядит как-то так:

String.Format ("[Line {0}:{{{1},{2}{6}-{{{3},{4}{6}:{5}]",
               File, Row, Column, EndRow, EndColumn, Offset, '}');
Спасибо. Поправлю статью.
Что-то вы как-то статью наполовину поправили…
upd. Добрался до компьютера со студией и проверил. Я был не прав, закрывающая фигурная скобка прекрасно экранируется. Теперь уже и не вспомню, что за баг я с ней ловил…

Впрочем, еще одно исправление статьи, где «лишние» фигурные скобки вообще исчезли, похоже на правду.
Нет. Это расширение (plug-in) для Visual Studio. Проверка происходит на той машине, где запущена VS. Исходники никуда не отправляются.
Можно запускать на сервере (например, ночные запуски). Но это другое.
Просто при отключенном интернете у меня ничего не сработало. Когда включил, то код был проверен. Вот я и засомневался
К сожалению не получилось запустить даже на пустом консольном проекте.
При «Check -> Solution» получаю: «The tools version „14.0“ is unrecognized. Available tools versions are „12.0“, „2.0“, „3.5“, „4.0“. c:\users\johndoe\documents\visual studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2.csproj 0»

Visual Studio Ultimate 2013
Пробовал target framework .net 4.5 и 3.5 — результат одинаков
Target Framework тут ни при чем, Tools Version — это версия MSBuild.

Вообще такая ситуация выглядит странно, обычно с 2013й студией идет 12я версия MSBuild, а не 14я. Можете попробовать поправить в файле проекта этот номер любым текстовым редактором (только не на 12.0, а на 4.0 — версии 12.0 у вас может и не быть, а 4.0 ставится с фреймворком) — если повезет, то все заработает. А если не повезет — вернуть обратно всегда можно.
Тогда проверьте файл решения. По опыту, там можно вообще чуть ли не любую версию писать — студия съест :)
Пришлите пожалуйста тестовый проект, на котором повторяется ошибка на support@viva64.com, мы посмотрим, что можно сделать.
Хотели выполнить некоторые действия, если 'node' наследуется от интерфейса 'ISolutionFolderNode'. Но проверили не ту переменную.

У некоторых дотнетчиков есть дурная привычка использовать безопасное приведение типа вместо обычного, будто падать с NullReferenceException лучше, чем InvalidCastException. Этот код может подразумевать, что интерфейс ISolutionFolderNode реулизуется node в любом случае, но node может быть null. Хотя, конечно, ваша версия выглядит более вероятной, но здесь прослеживается разница между плюсами и шарпом: в дотнете меньше боятся null, это не сразу убивает приложение. Может оказаться, что исправлением будет изменение способа приведения типа.
Visual Studio 2008, судя по всему, не поддерживаете? Хотел проверить рабочий проект, у нас достаточно интересный кейс: софт под WinCE, пишется в VS2008.
Да, VS2005 и VS2008 более не поддерживается. Для клиентов (С++), использующих старые Visual Studio будет некоторое время существовать параллельная версия 5.xx.
Ваша логика понятна, но, тем не менее, жаль. VS2008 — последняя студия с поддержкой разработки под WinCE.
Пример:
   public Task<bool> GetTwoFactorEnabledAsync(User user)
    {
      return Task.FromResult(false);
    }

    public Task<bool> GetLockoutEnabledAsync(User user)
    {
      return Task.FromResult(false);
    }

Показывается варнинг V3013, не должен, функции слишком элементарные
Как я понимаю вы не будете использовать roslyn для c#?
Как раз его мы и используем.
Из замеченного сразу:
Если в асинхронном коде есть периодические проверки на IsCancellationRequested с соответствующим return, то PVS-Studio выдаёт предупреждение, что все остальные проверки IsCancellationRequested бессмысленны, но это не так.

Пару странных опечаток с лёгкостью было найдено: повтор логического условия, которое зачем-то продублировали, а также присвоение значения самому себе, повторное присвоение значения…

Unconditional 'return' within a loop можно было бы сделать и high severity — уж очень подозрительная вещь

Было обнаружено две функции с одинаковым телом, но разной сигнатурой: у одной есть аргумент, но он не использовался — можно было такое показывать с severity повыше, чем low
Если в асинхронном коде есть периодические проверки на IsCancellationRequested с соответствующим return, то PVS-Studio выдаёт предупреждение, что все остальные проверки IsCancellationRequested бессмысленны, но это не так.

Тоже самое, если мы проверяем volatile bool — можно бы и догадаться, что переменная volatile может поменяться.
Тогда ещё и под lock'ом переменные, все явные чтения Volatile.Read и всё, что с MemoryBarrier, но там можно много всего интересного найти из способов выстрелить в ногу лёгким движением левой пятки компилятора, ибо модель памяти такая.
Если в асинхронном коде есть периодические проверки на IsCancellationRequested с соответствующим return, то PVS-Studio выдаёт предупреждение, что все остальные проверки IsCancellationRequested бессмысленны, но это не так.

Да это и без асинхронии «не так»: последовательные обращения к любому свойству/методу могут давать разные значения (по крайней мере, до тех пор, пока в CLR не появится явного указания на детерминированность метода).
Не совсем так. Спецификация говорит, что для кода без volatile, синхронизаций и прочего, вполне законны любые перестановки, которые законны для однопоточного кода. Справедливости ради, стоит заметить, что проверка IsCancellationRequested в итоге сводится к проверке значения поля, которое объявлено так:
private volatile int m_state
Спецификация говорит, что для кода без volatile, синхронизаций и прочего, вполне законны любые перестановки, которые законны для однопоточного кода.

А перестановка вызовов методов законна для однопоточного кода?
Понятно, что с точки зрения компилятора геттер свойства — вызов метода, про чистоту которого ничего неизвестно, но я пытаюсь сказать, что геттер вполне законно может быть заинлайнен, а значения используемых в нём переменных сохранены в регистры и не перечитываться, если они не помечены volatile или не синхронизированы иным образом. Соответственно, в случае с IsCancellationRequested имеем volatile поле, обращение к которому идёт вместе с соответствующей инструкцией процессора, которая не даёт ему ни переместить чтение, ни использовать старое значение.
я пытаюсь сказать, что геттер вполне законно может быть заинлайнен, а значения используемых в нём переменных сохранены в регистры и не перечитываться, если они не помечены volatile или не синхронизированы иным образом

Эмм. Однопоточный код:

class A
{
  int _c = 0;
  public int C {get {return _c;}}
  public void Q () {/*меняет значение _с, не инлайнится*/}
}

void Foo()
{
  var a = new A();
  if (a.C != 0) return;
  a.Q();
  if (a.C != 0) return;
}


Вы правда хотите сказать, что ничего не мешает сначала заинлайнить геттер C, а потом прочитать значение a._c единожды?
Вы не так поняли. Перестановки и преобразования разрешены только те, которые не меняют результат в случае однопоточного кода. В данном примере два чтения не могут быть объединены в одно ни на стадии компиляции, ни на стадии jit, ни во время исполнения, так как присутствует запись. Если бы там не было записи в _с, то обе операции чтения могли быть вполне законно объединены в одну.
В данном примере два чтения не могут быть объединены в одно ни на стадии компиляции, ни на стадии jit, ни во время исполнения, так как присутствует запись.

… и это не зависит от volatile?

(мне, конечно, отдельно интересно, как определяется, присутствует ли запись)
В примере с методом компилятор не будет ничего перемещать относительно вызова метода просто потому, что для этого надо слишком много всего проверять и тогда компиляция длилась бы целую вечность. jit-компилятор вполне может заинлайнить вызов метода, но переставить операции чтения и записи одной и той же переменной он не вправе их переставлять просто потому, что это изменит поведения даже для однопоточного случая. Процессор во время исполнения в пределах одного потока тоже не будет ничего переставлять (но при этом может выполнять много чего одновременно, но на результате это не должно отражаться). В случае же если бы там не было записи, то jit легко мог бы объединить два чтения в одно, если поле не volatile.
В примере с методом компилятор не будет ничего перемещать относительно вызова метода просто потому, что для этого надо слишком много всего проверять и тогда компиляция длилась бы целую вечность.

Вот именно поэтому в общем случае два вызова даже одного и того же метода оптимизации не подлежат. В частном случае, когда оба они инлайнятся, и в результате инлайна получается два чтения одного филда, и между ними нет операций записи или выхода за пределы скоупа — тогда, может быть, будет оптимизация (на самом деле, все равно не факт, JIT весьма консервативен).

Запихивать всю эту логику в статический анализатор? Можно, конечно, но…
И не надо засовывать всю эту логику в анализатор. Я говорю о том, что для диагностики V3021 можно снизить количество false positive за счёт предварительного анализа стандартных библиотек (например, mscorlib) и создания списка исключений. Для примера с IsCancellationRequested несложно было понять, что метод не чистый, ибо там читается volatile поле.
Для примера с IsCancellationRequested несложно было понять, что метод не чистый, ибо там читается volatile поле.

Как раз наоборот, это чистый метод (он не меняет состояние объекта), он недетерминированный.

И с моей точки зрения эта диагностика должна быть opt-in; иными словами, по умолчанию, любой метод считается возвращающим разные значения при последовательных вызовах, а те методы, которые детерминированы, аннотируются отдельно.
Как раз наоборот, это чистый метод (он не меняет состояние объекта), он недетерминированный.

чистая функция, это функция, которая:
является детерминированной;
не обладает побочными эффектами.

Если функция недерминированная, то она по определению не может быть чистой.

И с моей точки зрения эта диагностика должна быть opt-in

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

Ох, опять терминологическое расхождение. Ладно, я не буду спорить, это к сути дела отношения не имеет.

Возможно у них есть статистика по подобным ошибкам,

Интересно, откуда.
Интересно, откуда.

Например, из проверяемых проектов. Прогнали анализатором, нашли N срабатываний V3021, поговорили с разработчиками и выяснили, что M из этих N оказалось ошибками. Далее, основываясь на критичности данных ошибок можно делать выводы о том какой severity должен быть у данной диагностики и надо ли переделывать её на opt-in.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Некоторые диагностики поддерживают это, некоторые нет. Мы рассмотрим возможность поддержать эту ситуацию во всех диагностиках. Спасибо.
В первую очередь интересны сообщения о падениях, глюках и т.п. Также мы будем благодарны за предложения по созданию интересных диагностик. И за явные ложные срабатывания тоже благодарны.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Лучше прислать проект и способ повторить на support@viva64.com (если проект публичный), ну и .plog конечно
НЛО прилетело и опубликовало эту надпись здесь
В идеале — прислать маленький примерчик, на котором повторяется падение. Но мы будем благодарны, если вы пришлёте хотя бы стек падения\plog, если такой возможности нет.
НЛО прилетело и опубликовало эту надпись здесь
Да, действительно есть такой нюанс, мы посмотрим, что можно с этим сделать. Пока что вы можете прислать просто plog, там все Fail будут видны. Его можно получить через команду меню PVS-Studio|Open/Save|Save Analysis Report As
НЛО прилетело и опубликовало эту надпись здесь
• a team of no more than 9 developers may use the product, the analyzer being installed only on one computer of each user;

У нас в команде 20+ человек сейчас. Я могу себе одному поставить, чтобы проверить общий код в тестовых целях?
Да.
В случае триала — да, конечно. Мы не заставляем сразу всех членов команды пользоваться триалом.
Не могу найти цены на продукт на вашем сайте. Подозреваю, что они должны быть напротив надписей вида
«10-30 разработчиков, лицензия на первый год
31-50 разработчиков, лицензия на первый год
51-70 разработчиков, лицензия на первый год»

но их там нет — таблица из одной колонки.
Для того чтобы получить цены, надо написать запрос на support@viva64.com. Это не всем нравится, но это более или менее стандартная практика для таких продуктов.
На странице FAQ, ссылка «Текущие цены смотрите на странице покупки.» ведёт туда, где цен нет. Непорядок.
Жаль, что Express Edition вы не поддерживаете. Это значит, что мелкие разработчики — мимо, хотя это и понятно — маленькие команды полную студию себе не купят, а значит, и ваш продукт — тоже. Печально…
Это не мы Express Edition не поддерживаем. Это Express Edition не поддерживает плагины, которым и является PVS-Studio. Зато мы поддерживаем Community Edition.
Community Edition хочет восьмёрку минимум. А у меня Виста. Десятку покупать надо, так как Виста уже Микрософтом списана де-факто, но всё откладываю до обновления проца, а то потом вопить будет, что активировали на 3 ядрах, а появилось 8 внезапно.
3 ядра? оО это оч странный процессор. Оно из семейства AMD чтоль?
Да, Athlon 415e, собираюсь поменять на Рптерон для АМ3 слота. Временная замена растянулась на год :) Только без холиваров :)
Висту до 10 все равно не обвновить афайк, только 7/8/8.1 вроде. А коробочная версия как позволяла переустановку на любое число любых компов произвольной конфигурации, так и сейчас позволяет. Учитывая, что 10 — это судя по всему надолго, есть смысл её купить уже сейчас, и не страдать с экспрессами.
Я 10-ку и так куплю, а вот студию покупать смысла не вижу — мне хватает и express/community варианта.
Так я про покупку студии ничего и не говорил — дома Community выше крыши для любых экспериментов.
Вы также можете попробовать command line версию. Для просмотра отчёта можно использовать утилиту Standalone.
Немедленно скачал и проверил Unity проект. PVS нашла кучу очепяток, но есть несколько моментов, которые могут быть вам интересны:

_isCastleInfo = (_structure as Castle) != null;

V3019, я не думаю, что тут проверка _structure на ноль. Хотя конечно _structure is Castle — более правильная.

 public IEnumerator ToAnimation()
{
        _position = Transform.position;
        _rotation = Transform.rotation.eulerAngles;

        yield return new WaitForSeconds(time);

        _position = Transform.position;
        _rotation = Transform.rotation.eulerAngles;
}


V3008, Здесь речь идет про корутину, поэтому значение может поменяться в другой задаче
Спасибо. Учли.
На такой код:

string.Format("{0}, {2}, {3}, {4}", p0, p1, p2, p3);

ругается правильно, но сообщение об ошибке немного неточное:

Incorrect format. A different number of actual arguments is expected while calling 'Format' function. Expected: 4. Present: 4.

Думаю правильнее «Expected: 5».
Разве не {1}? :)
Ну, формально, так как в строке есть {4}, то ожидается таки 5 аргументов :) Либо в сообщении нужно уточнять, что мол «нарушена нумерация параметров в строке формата», или «параметр {4} в строке форматирования никогда не используется».
Это уже поправлено. Спасибо. В целом о формате сообщения диагностики подумаем.
Кстати, если бы оно поддерживало работу в виде модуля для Юнити (Unity3D) — то я уверен, что сотню-другую лицензий вы бы продали. Даже по 200 баксов за лицензию. Хотя, по сравнению со стоимостью подписки на полную версию — это не так уж и много.
Хммм, ну тоже вариант.
Спасибо, инструмент уже может порадовать. В решении 1 000 000 строк кода нашел 64 варнингов первого приоритета. Для даже не беты считаю уже не плохо. Особенно удивил код в одном из старых не используемых классах:

if (this.urlBox != null)
   {
    while (this.testHyperLinkControl != null)
    {
     this.testHyperLinkControl.NavigateUrl = "javascript:TestURL('" + SPHttpUtility.EcmaScriptStringLiteralEncode(this.urlBox.ClientID) + "')";
     break;
    }
   }
Прогнал 2 проекта: сервер и клиент, в сервере нашлась V3027 в длинном куске LINQ (использовал string.StartsWith перед string.IsNullOrWhiteSpace), в клиенте же я ещё не успел нашкодить.

Спасибо за предоставленную возможность проверить проекты!
Примечание. По аналогии с C++ принимаются «заявки» на проверку проектов. Прошу присылать названия интересных открытых C#-проектов. Будем их потихоньку проверять.
Первая мысль которя возникла это Roslyn :)
Да, будет. Думаю проверкой этого проекта ознаменуется выход Release-версии.
Попробовал на своих проектах. Ощущения странные.

В одном проекте нашёл явно излишнее повторное присваивание, в другом — явно лишнюю проверку условия. Отлично.

Кроме этого, нашёл повторное присваивание в подобном коде:

int step = 1;
try
{
  FirstFunction ();
  step = 2;
  SecondFunction ();
  step = 3;
  ThirdFunction ();
}
catch (Exception exception)
{
  Print ("Exception at step {0}: {1}", step, exception);
}

Согласен, что это странный способ отладки (кто, кстати, предложит лучше?), но подобное предупреждение лично я могу и игнорировать.

По-настоящему удивило другое. Открыл другой solution, запустил проверку — увидел, что он проверяет 4 файла (уже странно, там гораздо больше файлов) и через небольшое время поздравляет меня с тем, что замечаний у него к моему коду нет. Однако в этом solution'е тоже присутствует мой метод отладки с переменной step — к нему нет замечаний. Подозреваю, что PVS-Studio просто не обрабатывал этот файл.

Запускал проверку из Visual Studio 2010, этот solution впервые был создан какой-то первой версией Visual Studio для C#, затем последовательно апргейдился последующими версиями Visual Studio — возможно, поэтому оказался несовместимым с проверкой PVS-Studio.

Или это ограничения ознакомительной версии?
Проверьте, пожалуйста, какую платформу\конфигурацию вы проверяете. Если для какой-либо конфигурации сборка проекта отключена, то PVS-Studio не будет проверять такой проект.
Не помогло. Включил сборку всех проектов (кроме Setup-ов) во всех конфигурациях и платформах — всё равно видит только 4 файла (и не ясно — какие именно).

Прошу проверить текущий файл — тоже не проверяет.
Что пишется, когда пытаетесь проверить один файл? А если проверить один проект (через контекстное меню в Solution Explorer)? Solution включает обычные csproj проекты?

Также можно попробовать проверить solution напрямую из командной строки с помощью PVS-Studio_Cs.exe, возможно проблема на стороне Visual Studio плагина.
Один файл игнорирует — появляется окно прогресса, затем молча исчезает. Никаких сообщений не появляется.

Один проект через контекстное меню в Solution Explorer — появляется окно прогресса, затем молча исчезает. Никаких сообщений не появляется.

Solution включает в себя проекты csproj, уж не знаю — насколько они обычные, потому что создавались ранними версиями Visual Studio, затем апгрейдились более свежими версиями Visual Studio.

PVS-Studio_Cs.exe работает и даже находит какие-то ошибки, но намекает на необходимость заплатить. Так что похоже, что проблема действительно в плагине для Visual Studio.
В появляющемся окошке (при проверке одного проекта) указывается какое-то количество файлов?

Может быть файлы в проекты включены не как цели для компиляции (можно посмотреть в свойствах файла)? Также отдельные участки кода не будут проверены, если они заключены в define'ы, не определённые для проверяемого проекта.

Если возможно, пришлите пожалуйста csproj файл на support@viva64.com, мы попробуем разобраться.
Вариант получше: просто запустить в дебаг режиме, и при необработанном исключении у вас остановится программа и будет точное место и контекст.
Или при обработанном исключении, но если оно вышло за пределы пользовательского кода…
Это понятно.
Проблема в отладке в рабочем окружении, которое трудно воспроизвести в лаборатории. Приходится выводить отладочную печать, но так как объём кода большой, то хочется сначала приблизительно локализовать проблему, а потом ловить её точнее.
Всем, кому интересна эта тема. Мы выпустили релизную версию PVS-Studio 6.00 с поддержкой C#. Приглашаю скачать и попробовать: www.viva64.com/ru/pvs-studio-download
НЛО прилетело и опубликовало эту надпись здесь
Вы будете смеяться, но это было сделано специально. Программистам угодить невозможно. Многие писали, что они никогда не будут нажимать большую кнопку-картинку и что следует сделать скачку обыкновенной ссылкой. Так мы и поступили.
А почему нельзя начинать закачку по нажатию и на большую кнопку, и на ссылку?
Дело в том, что всем программистам не угодишь :). Так раньше и было. Но потом мы пришли к выводу, что программисты должны в начале получить информацию что они скачивают. Был негатив на тему, что их не предупредили перед скачиванием, например, о Visual Studio.
Это не объясняет, зачем вообще нужна большая кнопка, ведущая на ту же самую страницу.
Версия PVS-Studio уже не экспериментальная и в проекте SharpDevelop найдена ещё одна интересная ошибка:

V3038 The first argument of 'Replace' function is equal to the second argument. — ReflectionDisassembler.cs 349

void
WriteSecurityDeclarationArgument(CustomAttributeNamedArgument na)
{
  ....
  output.Write("string('{0}')",
    NRefactory.CSharp.TextWriterTokenWriter.
    ConvertString((string)na.Argument.Value).Replace("'", "\'"));
  ....
}

Обратите внимание на аргументы функции Replace(). Здесь планировалось заменить одну кавычку на экранированную кавычку, но в действительности происходит замена кавычки на кавычку и строка не изменяется.

Правильная запись должна выглядеть следующим образом:
....Replace("'", "\\'"));

Зарегистрируйтесь на Хабре, чтобы оставить комментарий