Аннотации для разыменования NULL в Prefast и компиляции на GCC

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

int Function(classA* pInput) {
   if (pInput == NULL) {
      classA::Create(pInput);
   }

   return pInput->value;
}

Проблема в том, что, поскольку Prefast оценивает только функцию, он не знает, что Create инициализирует указатель.

Я думал, что смогу решить это с помощью __out аннотация в заголовочном файле для classA::Create Однако это не сработало.

Мне интересно, есть ли хорошая альтернатива просто __analysis_assume повсюду в коде такой, что prefast выбирает его из определения функции.

Во-вторых, мне было интересно, как мне настроить конфигурацию сборки так, чтобы я мог собирать свой код непосредственно в Linux или с GCC с этими директивами препроцессора. Должен ли я проверить, находится ли он в сборке LINUX, а затем добавить эти аннотации в виде пустых макросов?

2 ответа

Решение

Ответ MSalter очень похож на правильный технический ответ. К счастью, я не знаю SAL, поэтому не могу сказать наверняка, но похоже, что это решение технического уровня.

Тем не менее, я бы порекомендовал вам переписать ваш текущий код...

int Function(classA* pInput) {
   if (pInput == NULL) {
      classA::Create(pInput);
   }

   return pInput->value;
}

как …

int Function( classA* pInput ) {
   if (pInput == NULL) {
      pInput = classA::Create();
   }

   return pInput->value;
}

Основная проблема здесь - утечка динамически созданного объекта или нет. Это очень зависит от того, что Create метод делает. Но похоже, ты протекаешь.

И в том случае, когда Create ничего не делает, но динамически выделяет инициализированный по умолчанию classA объект, то вот как вы можете сделать это более безопасно и более эффективно:

int Function( classA* pInput ) {
   if (pInput == NULL) {
      return classA().value;
   }

   return pInput->value;
}

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

int function( ClassA const& anObject = ClassA() )
{
   return anObject.value;
}

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

Это проще, безопаснее и эффективнее.

И - на уровне C++ вам обычно не приходится бороться с глупыми нотациями SAL.:-)

Ура & hth.,

Похоже, SA не хватает [Post( Null=No )] на classA*& параметр classA::Create(classA*)

Другие вопросы по тегам