Карта неточно анализируемая функция к стандартной функции для точного анализа
-function-behavior-specifications
file_path
-function-behavior-specifications
задает путь к XML-файлу. Можно использовать этот XML-файл, чтобы сопоставить некоторые функции к соответствующим стандартным функциям, которые распознает Polyspace®. Если при запуске верификацию из командной строки, file_path
file_path
является абсолютным путем или путем относительно папки, от которой вы запускаете команду. Если при запуске верификацию от пользовательского интерфейса, file_path
является абсолютным путем.
Если при запуске анализ от пользовательского интерфейса (только десктопные решения Polyspace) на панели Configuration, можно ввести эту опцию в поле Other. Смотрите Other
.
Этот раздел применяется только к анализу Программы автоматического доказательства Кода.
Используйте эту опцию, чтобы сократить количество оранжевых проверок от неточного анализа вашей функции. Иногда, верификация не анализирует определенные виды функций точно из-за свойственных ограничений в статической верификации. В тех случаях, если вы находите стандартную функцию, которая является близким аналогом вашей функции, используйте это отображение. Хотя ваша функция сама не анализируется, анализ более точен в местоположениях, где вы вызываете функцию. Например, если верификация не может анализировать ваш функциональный cos32
точно и рассматривает полный спектр для его возвращаемого значения, сопоставьте его с функцией cos
для возвращаемого значения в [-1,1].
Верификация игнорирует тело вашей функции. Однако верификация эмулирует ваше функциональное поведение следующими способами:
Верификация принимает те же возвращаемые значения для вашей функции как стандартная функция.
Например, если вы сопоставляете свой функциональный cos32
со стандартной функцией cos
, верификация принимает, что cos32
возвращает значения в [-1,1].
Верификация проверяет на те же проблемы, как она сверяется со стандартной функцией.
Например, если вы сопоставляете свой функциональный acos32
со стандартной функцией acos
, проверка Invalid use of standard library routine
определяет, находится ли аргумент acos32
в [-1,1].
function-behavior-specifications-sample.xml
файла примера показывает функции, что можно сопоставить с. Файл находится в
, где polyspaceroot\polyspace\verifier\cxx\
является папкой установки Polyspace. Функции, которые можно сопоставить, чтобы включать:polyspaceroot
Стандартные библиотечные функции от math.h
.
Управление памятью функционирует от string.h
.
__ps_meminit
: функционально-специализированное к Polyspace, который инициализирует область памяти.
Иногда, верификация не распознает, что ваша инициализация памяти функционирует, и производит оранжевый Non-initialized local variable
, проверяют переменную, которую вы инициализировали через эту функцию. Если вы знаете, что ваша функция инициализации памяти инициализирует переменную через свой адрес, сопоставьте свою функцию с __ps_meminit
. Проверка становится зеленой.
__ps_lookup_table_clip
: функционально-специализированное к Polyspace, который возвращает значение в области значений входного массива.
Иногда, верификация рассматривает полный спектр для возвращаемых значений функций, которые ищут значения в больших массивах (функции интерполяционной таблицы). Если вы знаете, что возвращаемое значение функции интерполяционной таблицы должно быть в области значений значений в ее входном массиве, сопоставьте функцию с __ps_lookup_table_clip
.
В коде, сгенерированном из моделей, верификация по умолчанию делает это предположение для функций интерполяционной таблицы. Чтобы идентифицировать, использует ли интерполяционная таблица линейную интерполяцию и никакую экстраполяцию, верификация использует имена функций. Используйте отображение только для рукописных функций, например, функций в Блоке s-function C/C++. Имена тех функций не следуют определенным соглашениям. Необходимо явным образом задать их.
Этот раздел применяется и к Средству поиска Ошибки и к анализу Программы автоматического доказательства Кода.
Используйте эту опцию для автоматического обнаружения функций создания потока и функций, которые начинают и заканчивают критические разделы. Polyspace поддерживает автоматическое обнаружение для определенных семейств многозадачных примитивов только. Расширьте поддержку с помощью этой опции.
Если ваша функция создания потока, например, не принадлежит одному из поддерживаемых семейств, сопоставьте свою функцию с поддерживаемым примитивным параллелизмом.
Чтобы найти, какие многозадачные примитивы могут быть автоматически обнаружены, смотрите Автоматическое обнаружение Создания Потока и Критического Раздела в Polyspace.
Можно адаптировать демонстрационный XML-файл отображения, которому предоставляют установку Polyspace, и сопоставить функцию со стандартной функцией.
Предположим, что верификация по умолчанию производит оранжевый User assertion
, проверяют этот код:
double x = acos32(1.0) ;
assert(x <= 2.0);
acos32
ведет себя как функциональный acos
, и возвращаемое значение 0. Вы ожидаете, что проверка на операторе assert
будет зеленой. Однако верификация полагает, что acos32
возвращает любое значение в области значений типа double
, потому что acos32
точно не анализируется. Проверка является оранжевой. Сопоставлять ваш функциональный acos32
с acos
:
Скопируйте файл function-behavior-specifications-sample.xml
от
до другого местоположения, например, polyspaceroot\polyspace\verifier\cxx\
"C:\Polyspace_projects\Common\Config_files"
. Измените полномочия записи на файле.
Чтобы сопоставить вашу функцию со стандартной функцией, измените содержимое XML-файла. Чтобы сопоставить ваш функциональный acos32
со стандартной библиотечной функцией acos
, измените следующий код:
<function name="my_lib_cos" std="acos"> </function>
<function name="acos32" std="acos"> </function>
Задайте местоположение файла для верификации:
Программа автоматического доказательства кода:
polyspace-code-prover -function-behavior-specifications "C:\Polyspace_projects\Common\Config_files\function-behavior-specifications-sample.xml"
Сервер программы автоматического доказательства кода:
polyspace-code-prover-server -function-behavior-specifications "C:\Polyspace_projects\Common\Config_files\function-behavior-specifications-sample.xml"
Иногда, аргументы вашей функции не сопоставляют непосредственный с аргументами стандартной функции. В тех случаях повторно сопоставьте свой аргумент функции с аргументом стандартной функции. Например:
__ps_lookup_table_clip
:
Это функционально-специализированное к Polyspace берет только массив интерполяционной таблицы в качестве аргумента и возвращает значения в области значений интерполяционной таблицы. Ваша интерполяционная таблица функциональная сила имеет дополнительные аргументы помимо самого массива интерполяционной таблицы. В этом случае используйте переотображение аргумента, чтобы задать, какой аргумент вашей функции является массивом интерполяционной таблицы.
Например, предположите, что функциональный my_lookup_table
имеет следующее объявление:
double my_lookup_table(double u0, const real_T *table, const double *bp0);
my_lookup_table
является массивом интерполяционной таблицы. В файле function-behavior-specifications-sample.xml
добавьте этот код:<function name="my_lookup_table" std="__ps_lookup_table_clip"> <mapping std_arg="1" arg="2"></mapping> </function>
Когда вы вызываете функцию:
res = my_lookup_table(u, table10, bp);
res =__ps_lookup_table_clip(table10);
res
находится в области значений значений в table10
.__ps_meminit
:
Это функционально-специализированное к Polyspace берет адрес памяти в качестве первого аргумента и многие байты в качестве второго аргумента. Функция принимает, что байты в памяти, начинающей с адреса памяти, инициализируются с допустимым значением. Ваша инициализация памяти функциональная сила имеет дополнительные аргументы. В этом случае используйте переотображение аргумента, чтобы задать, какой аргумент вашей функции является начальным адресом и какой аргумент является количеством байтов.
Например, предположите, что функциональный my_meminit
имеет следующее объявление:
void my_meminit(enum InitKind k, void* dest, int is_aligned, unsigned int size);
function-behavior-specifications-sample.xml
добавьте этот код:<function name="my_meminit" std="__ps_meminit"> <mapping std_arg="1" arg="2"></mapping> <mapping std_arg="2" arg="4"></mapping> </function>
Когда вы вызываете функцию:
my_meminit(INIT_START_BY_END, &buffer, 0, sizeof(buffer));
__ps_meminit(&buffer, sizeof(buffer));
sizeof(buffer)
байтов, начинающих с &buffer
, инициализируется.memset
: Переменное количество аргументов.
Если ваша функция имеет переменное количество аргументов, вы не можете сопоставить его непосредственно со стандартной функцией без явного переотображения аргумента. Например, скажите, что ваша функция объявляется как:
void* my_memset(void*, int, size_t, ...)
memset
, используйте следующее отображение:<function name="my_memset" std="memset"> <mapping std_arg="1" arg="1"></mapping> <mapping std_arg="2" arg="2"></mapping> <mapping std_arg="3" arg="3"></mapping> </function>
Эти примеры показывают результат отображения определенных функций к стандартным функциям:
my_acos
→ acos
:
Если вы используете отображение, проверка User assertion
становится зеленой. Верификация принимает, что возвращаемое значение my_acos
0.
Перед отображением:
double x = my_acos(1.0);
assert(x <= 2.0);
Отображение спецификации:
<function name="my_acos" std="acos"> </function>
После отображения:
double x = my_acos(1.0);
assert(x <= 2.0);
my_sqrt
→ sqrt
:
Если вы используете отображение, проверка Invalid use of standard library routine
покраснела. В противном случае верификация не проверяет, является ли аргумент my_sqrt
неотрицательным.
Перед отображением:
res = my_sqrt(-1.0);
Отображение спецификации:
<function name="my_sqrt" std="sqrt"> </function>
После отображения:
res = my_sqrt(-1.0);
my_lookup_table
(аргумент 2) →__ps_lookup_table_clip
(аргумент 1):
Если вы используете отображение, проверка User assertion
становится зеленой. Верификация принимает, что возвращаемым значением my_lookup_table
является в области значений массива интерполяционной таблицы table
.
Перед отображением:
double table[3] = {1.1, 2.2, 3.3}
.
.
double res = my_lookup_table(u, table, bp);
assert(res >= 1.1 && res <= 3.3);
Отображение спецификации:
<function name="my_lookup_table" std="__ps_lookup_table_clip"> <mapping std_arg="1" arg="2"></mapping> </function>
После отображения:
double table[3] = {1.1, 2.2, 3.3}
.
.
res_real = my_lookup_table(u, table9, bp);
assert(res_real >= 1.1 && res_real <= 3.3);
my_meminit
→__ps_meminit
:
Если вы используете отображение, проверка Non-initialized local variable
становится зеленой. Верификация принимает, что все поля структуры x
инициализируются с допустимыми значениями.
Перед отображением:
struct X {
int field1 ;
int field2 ;
};
.
.
struct X x;
my_meminit(&x, sizeof(struct X));
return x.field1;
Отображение спецификации:
<function name="my_meminit" std="__ps_meminit"> <mapping std_arg="1" arg="1"></mapping> <mapping std_arg="2" arg="2"></mapping> </function>
После отображения:
struct X {
int field1 ;
int field2 ;
};
.
.
struct X x;
my_meminit(&x, sizeof(struct X));
return x.field1;
my_meminit
→__ps_meminit
:
Если вы используете отображение, проверка Non-initialized local variable
покраснела. Верификация принимает, что только поле field1
структуры x
инициализируется с допустимыми значениями.
Перед отображением:
struct X {
int field1 ;
int field2 ;
};
.
.
struct X x;
my_meminit(&x, sizeof(int));
return x.field2;
Отображение спецификации:
<function name="my_meminit" std="__ps_meminit"> </function>
После отображения:
struct X {
int field1 ;
int field2 ;
};
.
.
struct X x;
my_meminit(&x, sizeof(int));
return x.field2;
В этом примере поддержка Polyspace автоматического обнаружения параллелизма расширена путем отображения неподдерживаемых функций с поддерживаемыми функциями Pthreads
.
Функция создания потока: createTask
→ pthread_create
Функция, которая начинает критический раздел: takeLock
→ pthread_mutex_lock
Функция, которая заканчивает критический раздел: releaseLock
→ pthread_mutex_unlock
Если вы используете отображение, анализ Средства поиска Ошибки может определить многозадачную модель, используемую в вашем коде, и найти возможные условия состязания.
Перед отображением:
Анализ не обнаруживает гонку данных на var2
.
typedef void* (*FUNT) (void*); extern int takeLock(int* t); extern int releaseLock(int* t); // First argument is the function, second the id extern int createTask(FUNT,int*,int*,void*); int t_id1,t_id2; int lock; int var1; int var2; void* task1(void* a) { takeLock(&lock); var1++; var2++; releaseLock(&lock); return 0; } void* task2(void* a) { takeLock(&lock); var1++; releaseLock(&lock); var2++; return 0; } void main() { createTask(task1,&t_id1,0,0); createTask(task2,&t_id2,0,0); }
Отображение спецификации:
На основе номера и типа параметров функционального createTask
, удобно сопоставить createTask
с функцией создания потока pthread_create
. Другие доступные альтернативы, createThread
или OSTaskCreate
, имеют различные типы аргумента.
Сопоставляя с pthread_create
, переотображение аргумента требуется, потому что аргументы не соответствуют точно. Поток запускается, стандартная программа является третьим аргументом pthread_create
, но первым аргументом createTask
.
<function name="createTask" std="pthread_create" > <mapping std_arg="1" arg="2"></mapping> <mapping std_arg="3" arg="1"></mapping> <mapping std_arg="2" arg="3"></mapping> <mapping std_arg="4" arg="4"></mapping> </function> <function name="takeLock" std="pthread_mutex_lock" > </function> <function name="releaseLock" std="pthread_mutex_unlock" > </function>
Для списка поддерживаемых функций, с которыми можно сопоставить, смотрите, что демонстрационное сопоставляет файл function-behavior-specifications-sample.xml
в
. polyspaceroot\polyspace\verifier\cxx\
является папкой установки Polyspace, такой как polyspaceroot
C:\Program Files\Polyspace\R2019a
. См. также Автоматическое обнаружение Создания Потока и Критического Раздела в Polyspace.
После отображения:
Анализ обнаруживает гонку данных на var2
.
typedef void* (*FUNT) (void*);
extern int takeLock(int* t);
extern int releaseLock(int* t);
// First argument is the function, second the id
extern int createTask(FUNT,int*,int*,void*);
int t_id1,t_id2;
int lock;
int var1;
int var2;
void* task1(void* a) {
takeLock(&lock);
var1++;
var2++;
releaseLock(&lock);
return 0;
}
void* task2(void* a) {
takeLock(&lock);
var1++;
releaseLock(&lock);
var2++;
return 0;
}
void main() {
createTask(task1,&t_id1,0,0);
createTask(task2,&t_id2,0,0);
}