metrica
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

Вебинар: Трудности при интеграции SAST, как с ними справляться - 04.04

>
>
Итак, вы хотите заглушить это предупреж…

Итак, вы хотите заглушить это предупреждение в Visual C++...

21 Авг 2013

Обычная ситуация: вы написали кусок безупречно правильного кода, но Visual C++ выдает на нем предупреждение. Часто можно немного переписать код, чтобы предупреждение ушло, но не всегда, и тогда выход один - глушить выдачу этого предупреждения. Рассмотрим, какие возможности для этого есть в Visual C++ и какие ошибки допускают при их использовании.

Статью написал сотрудник компании ABBYY Дмитрий Мещеряков, впервые опубликована: "Блог компании ABBYY. Итак, вы хотите заглушить это предупреждение в Visual C++..." Публикуется здесь с разрешения правообладателя.

Мы решили опубликовать эту статью в базе знаний, так как она очень хорошо поясняет назначение диагностики V665, реализованную в PVS-Studio.

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

Следующая возможность - запретить предупреждение в настройках проекта на уровне файла. Этот способ еще хуже предыдущего. Во-первых, предупреждение будет заглушено на всю единицу трансляции, т.е. в этом файле и всех заголовках, которые он включает. Во-вторых, точно те же проблемы с копированием кода, что и в прошлый раз. В-третьих, как только в проекте оказывается больше нескольких файлов, вероятность потерять эту настройку при конверсии проекта под более новую версию Visual C++ становится равной чуть менее, чем единице.

Остается использование #pragma warning. Обычно ее используют так:

#pragma warning (disable: 9000)
// код, провоцирующий предупреждение C9000
#pragma warning (default: 9000)

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

На самом деле, это FAIL. Пора внимательно прочитать (да, внимательно и да, прочитать, а не копипастить код откуда попало) описание #pragma warning (default). Там говорится следующее: эта конструкция

  • Устанавливает предупреждению уровень по умолчанию и
  • Включает предупреждение.

Сначала уровни. В Visual C++ с каждым предупреждением связано число от 1 до 4 - это уровень предупреждения. Предупреждения уровня 1 считаются более серьезными, с ростом уровня серьезность якобы снижается. У каждого предупреждения есть уровень по умолчанию. Конструкция

#pragma warning(Level: Warning)

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

У компилятора есть настройка, с какого уровня предупреждения показывать, Warning Level. При значении этой настройки, равном A, предупреждение в конкретной строке кода показывается только в том случае, если оно там разрешено и его уровень составляет A или ниже.

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

Рассмотрим, как проявляется FAIL при использовании #pragma warning (default).

FAIL 1. Предупреждение C9001 выключено по умолчанию. Код в заголовочном файле использует #pragma warning(default:9001), чтобы "восстановить" предупреждение, заглушенное в небольшом куске кода.

Зачем он это делает, если предупреждение и так выключено? Список предупреждений, выключенных по умолчанию, меняется от одной версии Visual C++ к другой - в него понемногу добавляются предупреждения. Если код изначально писали для Visual C++ 7, а там C9001 по умолчанию было включено, а теперь компилируют в Visual C++ 10, и в нем предупреждение уже выключено, то такая конструкция смысла не имеет, а могла просто достаться в наследство.

В результате #pragma warning(default) принудительно включает предупреждение, выключенное по умолчанию.

FAIL 2. У предупреждения C9002 уровень по умолчанию 3, а проект компилируется с уровнем 2, т.е. "показывать предупреждения уровня 2 и ниже". После долгих раздумий разработчики решили, что на самом деле предупреждение C9002 достаточно серьезное, чтобы удостоить его уровня 2, т.е. принудительно повысить серьезность. Соответственно, каждый проект включает в себя стандартный заголовок, попадающий затем во все единицы трансляции, который содержит конструкцию #pragma warning(2:9002).

Чуть ниже по тексту в единице трансляции оказывается #pragma warning(default:9002), которая сбрасывает уровень обратно на 3, и при компиляции с уровнем 2 предупреждение не выдается. Кстати, это предупреждение сообщало о серьезном дефекте. Улыбаемся и машем. В обратную сторону тоже работает — предупреждению "повысили" уровень с 2 до 3, чтобы оно не выдавалось в проектах, компилируемых с уровнями 2 и ниже (т.е. понизили серьезность), но #pragma warning(default) сбрасывает уровень на 2, и предупреждение выдается.

FAIL 3. Предупреждение C9003 по умолчанию включено, но продумано так плохо, что никто не может припомнить, когда оно выдается по делу. Разработчики решаются заглушить его повсюду, использовав #pragma warning(disable:9003) в общем заголовочном файле. Ниже по единице трансляции оказывается #pragma warning(default:9003), которая включает предупреждение.

Что особенно приятно, эти ситуации возникают в самый подходящий момент - при переходе с одной версии компилятора на другую, при попытке включить в проект кучу стороннего кода, который и без того не прост в использовании, вторая ситуация просто приводит к подавлению предупреждения, в результате можно пропустить ошибку в коде, которая позже поможет пользователям получить премию Дарвина.

На самом деле, предупреждения нужно глушить так:

#pragma warning(push)
// хорошие, годные вакансии: www.abbyy.ru/vacancy
#pragma warning(disable:9000)
// код с предупреждением C9000
#pragma warning(pop)

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

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

Популярные статьи по теме


Комментарии (0)

Следующие комментарии next comments
close comment form