-function-behavior-specifications

Карта неточно анализируемая функция к стандартной функции для точного анализа

Синтаксис

-function-behavior-specifications file1[, file2, [...]]

Описание

-function-behavior-specifications file1[, file2, [...]] задает XML-файлы, которые сопоставляют ваши библиотечные функции с соответствующими стандартными функциями, которые распознает Polyspace®. Отображение ваших библиотечных функций к стандартным функциям может помочь с улучшением точности или позволить автоматическое обнаружение потоков.

Если при запуске верификацию из командной строки, задаете абсолютный путь к XML-файлам или пути относительно папки, от которой вы запускаете команду. Если при запуске верификацию от пользовательского интерфейса (только десктопные решения), задаете абсолютный путь в поле Other.

Используя опцию для улучшения точности

Этот раздел применяется только к анализу Программы автоматического доказательства Кода.

Используйте эту опцию, чтобы сократить количество оранжевых проверок от неточного анализа вашей функции. Иногда, верификация не анализирует определенные виды функций точно из-за свойственных ограничений в статической верификации. В тех случаях, если вы находите стандартную функцию, которая является близким аналогом вашей функции, используйте это отображение. Хотя ваша функция сама не анализируется, анализ более точен в местоположениях, где вы вызываете функцию. Например, если верификация не может анализировать ваш функциональный cos32 точно и рассматривает полный спектр для его возвращаемого значения, сопоставьте его с cos функция для возвращаемого значения в [-1,1].

Верификация игнорирует тело вашей функции. Однако верификация эмулирует ваше функциональное поведение следующими способами:

  • Верификация принимает те же возвращаемые значения для вашей функции как стандартная функция.

    Например, если вы сопоставляете свой функциональный cos32 к стандартной функции cos, верификация принимает тот cos32 возвращает значения в [-1,1].

  • Верификация проверяет на те же проблемы, как она сверяется со стандартной функцией.

    Например, если вы сопоставляете свой функциональный acos32 к стандартной функции acosInvalid use of standard library routine проверка определяет если аргумент acos32 находится в [-1,1].

Файл примера function-behavior-specifications-sample.xml показывает функции, что можно сопоставить с. Файл находится в polyspaceroot\polyspace\verifier\cxx\ где polyspaceroot папка установки Polyspace. Функции, которые можно сопоставить, чтобы включать:

  • Стандартные библиотечные функции от 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:

  1. Скопируйте файл function-behavior-specifications-sample.xml от polyspaceroot\polyspace\verifier\cxx\ к другому местоположению, например, "C:\Polyspace_projects\Common\Config_files". Измените полномочия записи на файле.

  2. Чтобы сопоставить вашу функцию со стандартной функцией, измените содержимое XML-файла. Сопоставлять ваш функциональный acos32 к стандартной библиотечной функции acos, измените следующий код:

    <function name="my_lib_cos" std="acos"> </function>
    К:
    <function name="acos32" std="acos"> </function>

  3. Задайте местоположение файла для верификации:

    • Программа автоматического доказательства кода:

      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_acosacos:

    Если вы используете отображение, 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_sqrtsqrt:

    Если вы используете отображение, 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 функции.

  • Функция создания потока: createTaskpthread_create

  • Функция, которая начинает критический раздел: takeLockpthread_mutex_lock

  • Функция, которая заканчивает критический раздел: releaseLockpthread_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\. polyspaceroot папка установки Polyspace, такая как 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);
    }
    

Введенный в R2017b