Как правильно переписать, УТВЕРЖДАЮТ, что код для передачи / анализирует в msvc?

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

Большинство проблем генерирует, потому что старый код делает, некоторые УТВЕРЖДАЮТ в начале метода или функции.

Я думаю, что это - УТВЕРЖДАТЬ определение, используемое в коде (от afx.h)

#define ASSERT(f)          DEBUG_ONLY((void) ((f) || !::AfxAssertFailedLine(THIS_FILE, __LINE__) || (AfxDebugBreak(), 0)))

Пример кода:

ASSERT(pBytes != NULL);
*pBytes = 0; // <- warning C6011: Dereferencing NULL pointer 'pBytes'

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

10
задан sorin 9 April 2010 в 13:31
поделиться

5 ответов

PREFast говорит вам, что в вашем коде есть дефект; не игнорируйте его. На самом деле он у вас есть, но вы лишь обходите его стороной. Проблема в следующем: если pBytes никогда не был NULL в разработке и тестировании, это не значит, что его не будет в производстве. Вы не справляетесь с этой случайностью. PREfast знает это, и пытается предупредить вас, что производственные среды враждебны, и оставят ваш код дымящейся, изуродованной массой бесполезных байтов.

/rant

Есть два способа исправить это: правильный способ и взлом.

Правильный способ - обрабатывать NULL-указатели во время выполнения:

void DoIt(char* pBytes)
{
    assert(pBytes != NULL);
    if( !pBytes )
        return;
    *pBytes = 0;
}

Это заставит PREfast замолчать.

Хак заключается в использовании аннотации. Например:

void DoIt(char* pBytes)
{
    assert(pBytes != NULL);
    __analysis_assume( pBytes );
    *pBytes = 0;
}

EDIT: Вот ссылка, описывающая аннотации PREfast. В любом случае, это отправная точка.

3
ответ дан 4 December 2019 в 02:25
поделиться

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

Нереалистично ожидать нулевых предупреждений с помощью / analysis.

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

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

Вы можете использовать специфичное для Microsoft расширение __ accept , чтобы сообщить компилятору, что он не должен выдавать это предупреждение, но лучшее решение - оставить это предупреждение. Каждый раз, когда вы компилируете / анализируете (что не обязательно каждый раз при компиляции), вы должны убедиться, что выдаваемые им предупреждения по-прежнему являются ложными.

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

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

Никогда не используйте утверждения для проблем, которые возможны . Используйте их, чтобы убедиться, что невозможное не происходит. И когда / alyze дает вам предупреждения, посмотрите на них.Если это ложное срабатывание, игнорируйте его (не подавляйте его, потому что, хотя сегодня это ложное срабатывание, код, который вы проверяете завтра, может превратить его в реальную проблему).

5
ответ дан 4 December 2019 в 02:25
поделиться

Вы, кажется, предполагаете, что ASSERT (ptr) каким-то образом означает, что ptr впоследствии не является NULL. Это неправда, и анализатор кода не делает этого предположения.

-1
ответ дан 4 December 2019 в 02:25
поделиться

помните, ASSERT () уходит из розничной сборки, поэтому предупреждение C6011 абсолютно правильное в приведенном выше коде: вы должны проверьте, что pBytes не равно нулю, а также выполните ASSERT (). ASSERT () просто передает ваше приложение в отладчик, если это условие выполняется в отладочной ошибке.

Я много работаю над / analysis и PREfast, поэтому, если у вас есть другие вопросы, дайте мне знать.

0
ответ дан 4 December 2019 в 02:25
поделиться

Мой соавтор Дэвид Леблан сказал бы мне, что этот код все равно не работает, если вы используете C ++, вам следует использовать ссылку, а не указатель, а ссылка может ' t быть NULL :)

-2
ответ дан 4 December 2019 в 02:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: