Аннотации для разыменования 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*)