Как спрашивается в заголовке:
Какова цель SAL (исходный язык аннотации) и в чем разница между SAL 1 и SAL 2?
Я понимаю основы использования, и это служит для того, чтобы подчеркнуть назначение каждой из переменных, передаваемых в функции, наряду с различными другими вещами для статического анализа кода, но насколько это существенно на самом деле (игнорирование растущей ясности требований к параметрам для другие программисты на проекте)?
Если бы у меня был следующий прототип:
_Success_(return == 1)
int TestFunction( _In_ int* pTest, _Inopt_ char* pOptional );
Предполагается, что это «скажет» статическому анализатору, что функция вернет 1 при успешной работе, что pTest
указатель, который не должен быть nullptr
и это pOptional
это указатель, который может или не может быть nullptr
, Однако разве статический анализатор не может получить эту информацию из определения самой функции? Кроме того, что это делает с информацией, которую получает, такой как критерии успеха?
Кроме того, почему есть разница между SAL 1 и SAL 2, почему Microsoft решила изменить способ, которым они назвали свои макросы (т.е. __out
в _Out_
а также __success
в _Success_
?)
Извините, если это где-то подробно описано в MSDN, но мне не удалось найти его или какой-либо другой вопрос в StackOverflow с подробным ответом, поэтому я решил спросить в надежде, что мое любопытство будет удовлетворено.
Спасибо заранее за ваше время!
Я прочитал несколько вопросов в вашем вопросе, надеюсь, я получил их все:
Зачем использовать SAL, а не просто выводить из источника?
Существует несколько ответов относительно того, как явно сообщить анализатору подробности о поведении параметров и т. Д. С помощью SAL.
Хотя анализатор может определить поведение параметров из реализации, он часто не может определить разницу между намерением и случайностями реализации. Как разработчик, если вы явно заявите о назначении различных параметров, анализатор может подтвердить, что вы написали реализацию, которая выполнила ваше намерение, а также, что вызывающие программы используют ее правильно.
Это дает статическим анализаторам информацию о поведении функций, когда исходный код недоступен для анализа, например, функции, объявленные в различных заголовочных файлах, поставляемых как часть Visual Studio, наборы драйверов и т. Д.
SAL позволяет выражать понятия, которые трудно или невозможно вывести только из исходного кода, такие как использование блокировки и требования IRQL в драйверах.
Это также помогает в согласованности с функциями обратного вызова. Некоторые платформы, описанные в заголовках Windows, могут объявлять набор функций обратного вызова, поэтому среда Windows будет вызывать те функции обратного вызова, которые определены в другом месте (приложения, драйверы и т. Д.). Таким образом, Windows никогда не видит источник вызываемых функций, а определения функций обратного вызова никогда не видят вызывающих.
Какую информацию получает анализатор успех?
Это не очень актуально в случае, когда вы написали. Однако в тех случаях, когда имеются выходные параметры (например, Из и семейство), это означает, что если функция не выполняется, вызывающая сторона не может полагаться на выходные аннотации. Так, например:
_Success_(return) bool GetASmallInt(_Out_range_(0, 10) int& an_int);
Если GetASmallInt возвращает true, an_int будет между 0 и 10 включительно. Если он возвращает false, такой гарантии не существует, и переменная может даже не быть инициализирована функцией.
В чем разница между SAL 1 и SAL 2 и почему аннотации были переименованы из __in
в _In_
?
Некоторые угловые случаи в первоначальном определении SAL (например, __in) плохо совмещались с C ++. Новый синтаксис начался с некоторой более новой реализации, которая убедилась, что он будет соответствовать требованиям грамматик C и C ++.
Основное различие между SAL 1 и SAL 2 связано с тем, что SAL 2 может выражать множество концепций, которые SAL 1 не может, и SAL 2 лучше определено, особенно в отношении C ++, как отмечено выше.
Других решений пока нет …