CERT C: правило DCL40-C

Не создавайте несовместимые объявления той же функции или объекта

Описание

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

Не создавайте несовместимые объявления той же функции или объекта. [1]

Примеры

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

Описание

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

Риск

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

Подобная проблема может произойти с несоответствием в объявлениях функции.

Фиксация

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

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

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

Пример - противоречивые объявления в двух файлах

file1.c

int foo(void) {
    return 1;
}

file2.c

double foo(void);

int bar(void) {
    return (int)foo();
}

В этом примере file1.c объявляет foo() как возврат целого числа. В file2.c foo() объявляется как возврат двойного. Это различие повышает дефект на втором экземпляре foo в file2.

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

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

file1.c

int foo(void) {
    return 1;
}

file2.c

int foo(void);

int bar(void) {
    return foo();
}

Пример - противоречивое выравнивание структуры

test1.c

#include "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

test2.c

#include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square;

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

circle.h

#pragma pack(1)

extern struct aCircle{ 
    int radius; 
} circle; 

square.h

extern struct aSquare { 
    unsigned int side:1; 
} square;

В этом примере дефект несоответствия объявления повышен на square в square.h, потому что Polyspace® выводит, что square в square.h не имеет того же выравнивания как square в test2.c. Эта ошибка происходит, потому что оператор #pragma pack(1) в circle.h объявляет определенное выравнивание. В test2.c circle.h включен прежде square.h. Поэтому оператор #pragma pack(1) от circle.h не сбрасывается к выравниванию по умолчанию после структуры aCircle. Из-за этого пропуска test2.c выводит, что структура aSquare square также имеет выравнивание байта 1.

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

Одно возможное исправление должно сбросить выравнивание структуры после объявления struct aCircle. Для GNU® или компиляторов Microsoft® Visual, зафиксируйте дефект путем добавления оператора #pragma pack() в конце circle.h.

test1.c

#include "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

test2.c

#include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square;

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

circle.h

#pragma pack(1)

extern struct aCircle{ 
    int radius; 
} circle; 

#pragma pack()

square.h

extern struct aSquare { 
    unsigned int side:1; 
} square;

Другие компиляторы требуют различного синтаксиса #pragma pack. Для вашего синтаксиса см. документацию для своего компилятора.

Исправление — использует опцию Ignore pragma pack directives

Одно возможное исправление должно добавить опцию Ignore pragma pack directives в ваш анализ Средства поиска Ошибки. Если вы хотите, чтобы выравнивание структуры изменилось для каждой структуры, и вы не хотите видеть этот дефект Declaration mismatch, использовать это исправление.

  1. На панели Настройки выберите панель Advanced Settings.

  2. В поле Other введите -ignore-pragma-pack.

  3. Повторно выполните свой анализ.

    Дефект Declaration mismatch разрешен.

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

Группа: правило 02. Объявления и инициализация (DCL)

Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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