CERT C: Rec. ARR02-C

Явным образом задайте границы массивов, даже если неявно заданный инициализатором

Описание

Управляйте определением

Явным образом задайте границы массивов, даже если неявно заданный инициализатором. [1]

Примеры

развернуть все

Описание

Проблема происходит, когда вы объявляете массив с внешней связью, но вы явным образом не задаете ее размер.

Средство проверки правила отмечает массивы, объявленные с помощью спецификатора extern, если объявление явным образом не задает размер массивов.

Риск

Несмотря на то, что возможно объявить массив с неполным типом и получить доступ к его элементам, более безопасно утвердить размер массива явным образом. Если вы предоставляете информацию о размере для каждого объявления, рецензент кода может проверять многократные объявления на их непротиворечивость. С информацией о размере инструмент статического анализа может выполнить анализ границ массивов, не анализируя больше чем один модуль.

Пример - объявления массива

extern int32_t array1[10];    /*  Compliant  */
extern int32_t array2[];      /*  Non-compliant  */

В этом примере два массива объявляются array1 и array2. array1 имеет внешнюю связь (ключевое слово extern) и размер 10. array2 также имеет внешнюю связь, но никакой заданный размер. array2 несовместим, потому что для массивов с внешней связью, необходимо явным образом задать размер.

Описание

Проблема происходит, когда вы используете обозначенные инициализаторы, чтобы инициализировать объект массивов, но вы не делаете explicitely задают размер массива.

Риск

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

Пример - Используя обозначенные инициализаторы, не задавая размер массивов

int a[5] = {[0]= 1, [2] = 1, [4]= 1, [1] = 1};        /* Compliant */
int b[] = {[0]= 1, [2] = 1, [4]= 1, [1] = 1};         /* Non-compliant */
int c[] = {[0]= 1, [1] = 1, [2]= 1, [3]=0, [4] = 1};  /* Non-compliant */

void display(int);

void main() {
    func(a,5);
    func(b,5);
    func(c,5);
}

void func(int* arr, int size) {
    for(int i=0; i<size; i++)
        display(arr[i]);
}

В этом примере нарушено правило, когда массивы, b и c инициализируются с помощью обозначенных инициализаторов, но размер массивов не задан.

Описание

Неподходящая инициализация массивов происходит, когда Polyspace® Bug Finder™ полагает, что инициализация массивов с помощью инициализаторов является неправильной.

Этот дефект применяется к нормальным и обозначенным инициализаторам. В C99, с обозначенными инициализаторами, можно поместить элементы инициализатора массивов в любом порядке и неявно инициализировать некоторые элементы массива. Обозначенные инициализаторы используют индекс массива, чтобы установить соответствие между элементом массива и элементом инициализатора массивов. Например, оператор int arr[6] = { [4] = 29, [2] = 15 } эквивалентен int arr[6] = { 0, 0, 15, 0, 29, 0 }.

Можно использовать инициализаторы неправильно одним из следующих способов.

ПроблемаРискВозможная фиксация

В вашем инициализаторе для одномерного массива у вас есть больше элементов, чем размер массивов.

Неиспользованные элементы инициализатора массивов указывают на возможную ошибку кодирования.

Увеличьте размер массивов или удалите избыточные элементы.

Вы помещаете фигурные скобки, заключающие значения инициализатора неправильно.

Из-за неправильного размещения фигурных скобок не используются некоторые элементы инициализатора массивов.

Неиспользованные элементы инициализатора массивов указывают на возможную ошибку кодирования.

Поместите фигурные скобки правильно.

В вашем обозначенном инициализаторе вы не инициализируете первый элемент массива явным образом.

Неявная инициализация первого элемента массива указывает на возможную ошибку кодирования. Вы возможно пропустили то, что индексация массива запускается от 0.

Инициализируйте все элементы явным образом.

В вашем обозначенном инициализаторе вы инициализируете элемент дважды.

Первая инициализация заменена.

Избыточная первая инициализация указывает на возможную ошибку кодирования.

Удалите избыточную инициализацию.

Вы используете обозначенные и необозначенные инициализаторы в той же инициализации.

Вы или другой рецензент вашего кода не можете определить размер массива контролем.

Используйте или обозначенные или необозначенные инициализаторы.

Фиксация

Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Комментарии.

Пример - неправильно помещенные фигурные скобки (C только)


int arr[2][3]
= {{1, 2},
    {3, 4},
    {5, 6}
};

В этом примере массив arr инициализируется как {1,2,0,3,4,0}. Поскольку инициализатор содержит {5,6}, вы можете ожидать, что массивом будет инициализированный {1,2,3,4,5,6}.

Исправление — фигурные скобки места правильно

Одно возможное исправление должно поместить фигурные скобки правильно так, чтобы все элементы были явным образом инициализированы.

int a1[2][3]
= {{1, 2, 3},
    {4, 5, 6}
};

Пример - первый элемент, не явным образом инициализированный

int arr[5]
= {
    [1] = 2,      
    [2] = 3,
    [3] = 4,
    [4] = 5
};              

В этом примере явным образом не инициализируется arr[0]. Возможно, что программист не полагал, что индексация массива запускается от 0.

Исправление — явным образом инициализирует все элементы

Одно возможное исправление должно инициализировать все элементы явным образом.

int arr[5]
= {
    [0] = 1,
    [1] = 2,      
    [2] = 3,
    [3] = 4,
    [4] = 5
};              

Пример - элемент, инициализированный дважды

int arr[5]
= {
    [0] = 1,
    [1] = 2,      
    [2] = 3,
    [2] = 4,
    [4] = 5
};              

В этом примере arr[2] инициализируется дважды. Первая инициализация заменена. В этом случае, потому что arr[3] не был явным образом инициализирован, возможно, что программист намеревался инициализировать arr[3], когда arr[2] был инициализирован во второй раз.

Исправление — фиксирует избыточную инициализацию

Одно возможное исправление должно устранить избыточную инициализацию.

int arr[5]
= {
    [0] = 1,
    [1] = 2,
    [2] = 3,
    [3] = 4,
    [4] = 5
};

Пример - соединение обозначенных и необозначенных инициализаторов

int arr[]
= {
    [0] = 1,
    [3] = 3,
    4,
    [5] = 5,
    6
    };              

В этом примере, потому что соединение обозначенных и необозначенных инициализаторов используется, трудно определить размер arr контролем.

Исправление — использует только обозначенные инициализаторы

Одно возможное исправление должно использовать только обозначенные инициализаторы для инициализации массивов.

int arr[]
= {
    [0] = 1,
    [3] = 3,
    [4] = 4,
    [5] = 5,
    [6] = 6
};              

Проверяйте информацию

Группа: Rec. 06. Массивы (ARR)

Введенный в R2019a


[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ-МЕЛЛОН И/ИЛИ ЕГО ИНСТИТУТА ПРОГРАММНОЙ ИНЖЕНЕРИИ СОДЕРЖАЛ, ЗДЕСЬ ПРЕДОСТАВЛЯЕТСЯ НА ОСНОВЕ "ASIS". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.