Вызовите функции с правильным номером и типом аргументов
Это средство проверки проверяет на эти проблемы:
Плохой режим доступа к файлу или состояние.
Ненадежный бросок указателя функции.
Вызов стандартной функции с неправильными аргументами.
Неподдерживаемые сложные аргументы
Несоответствие объявления функции
Плохой режим доступа к файлу или состояние происходят, когда вы используете функции в fopen
или open
группа с недопустимыми или несовместимыми режимами доступа к файлу, флагами создания файла или состоянием файла отмечает в качестве аргументов. Например, для open
функция, примеры допустимых:
Режимы доступа включают O_RDONLY
, O_WRONLY
, и O_RDWR
Флаги создания файла включают O_CREAT
, O_EXCL
, O_NOCTTY
, и O_TRUNC
.
Флаги состояния файла включают O_APPEND
, O_ASYNC
, O_CLOEXEC
, O_DIRECT
, O_DIRECTORY
, O_LARGEFILE
, O_NOATIME
, O_NOFOLLOW
, O_NONBLOCK
, O_NDELAY
, O_SHLOCK
, O_EXLOCK
, O_FSYNC
, O_SYNC
и так далее.
Дефект может произойти в следующих ситуациях.
Ситуация | Риск | Фиксация |
---|---|---|
Вы передаете пустой или недопустимый режим доступа Согласно стандарту ANSI® C, допустимым режимам доступа для
|
Некоторые реализации позволяют расширение режима доступа, такого как:
Однако ваша строка режима доступа должна начаться с одной из допустимых последовательностей. | Передайте допустимый режим доступа fopen . |
Вы передаете флаг O_APPEND состояния к open функция, не комбинируя его ни с одним O_WRONLY или O_RDWR . |
| Передайте любой O_APPEND|O_WRONLY или O_APPEND|O_RDWR как режим доступа. |
Вы передаете флаги состояния O_APPEND и O_TRUNC вместе к open функция. |
| В зависимости от того, что вы намереваетесь сделать, передайте один из этих двух режимов. |
Вы передаете флаг O_ASYNC состояния к open функция. | На определенных реализациях, режиме O_ASYNC не включает управляемые сигналом операции I/O. | Используйте fcntl(pathname, F_SETFL, O_ASYNC); вместо этого. |
Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Bug Finder в Пользовательском интерфейсе Рабочего стола Polyspace.
Смотрите примеры мер ниже.
Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
fopen
#include <stdio.h>
void func(void) {
FILE *file = fopen("data.txt", "rw");
if(file!=NULL) {
fputs("new data",file);
fclose(file);
}
}
В этом примере, режим доступа rw
недопустимо. Поскольку r
указывает, что вы открываете файл для чтения и w
указывает, что вы создаете новый файл для записи, эти два режима доступа несовместимы.
r
или w
как режим доступаОдна возможная коррекция должна использовать соответствие режима доступа, что вы намереваетесь сделать.
#include <stdio.h> void func(void) { FILE *file = fopen("data.txt", "w"); if(file!=NULL) { fputs("new data",file); fclose(file); } }
Ненадежный бросок указателя функции происходит, когда указатель функции брошен к другому указателю функции, который имеет различный аргумент, или возвратите тип.
Этот дефект применяется, только если кодовый язык для проекта является C.
Если вы бросаете указатель функции к другому указателю функции с различным аргументом или возвращаете тип и затем используете последний указатель функции, чтобы вызвать функцию, поведение не определено.
Избегайте броска между двумя указателями функции с несоответствием в аргументе или возвратите типы.
Смотрите примеры мер ниже.
Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
#include <stdio.h>
#include <math.h>
#include <stdio.h>
#define PI 3.142
double Calculate_Sum(int (*fptr)(double))
{
double sum = 0.0;
double y;
for (int i = 0; i <= 100; i++)
{
y = (*fptr)(i*PI/100);
sum += y;
}
return sum / 100;
}
int main(void)
{
double (*fp)(double);
double sum;
fp = sin;
sum = Calculate_Sum(fp);
/* Defect: fp implicitly cast to int(*) (double) */
printf("sum(sin): %f\n", sum);
return 0;
}
Указатель функции fp
объявляется как double (*)(double)
. Однако мимоходом это, чтобы функционировать Calculate_Sum
fp
неявно брошен к int (*)(double)
.
Одна возможная коррекция должна проверять что указатель функции в определение Calculate_Sum
имеет тот же аргумент, и возвратите тип как fp
. Этот шаг убеждается тот fp
неявно не брошен к различному аргументу, или возвратите тип.
#include <stdio.h> #include <math.h> #include <stdio.h> # define PI 3.142 /*Fix: fptr has same argument and return type everywhere*/ double Calculate_Sum(double (*fptr)(double)) { double sum = 0.0; double y; for (int i = 0; i <= 100; i++) { y = (*fptr)(i*PI/100); sum += y; } return sum / 100; } int main(void) { double (*fp)(double); double sum; fp = sin; sum = Calculate_Sum(fp); printf("sum(sin): %f\n", sum); return 0; }
Вызов стандартной функции с неправильными аргументами происходит, когда аргументы к функциям определенного стандарта не удовлетворяют требования для своего использования в функциях.
Например, аргументы к этим функциям могут быть недопустимыми следующими способами.
Функциональный тип | Ситуация | Риск | Фиксация |
---|---|---|---|
Обработка строк функционирует, такие как strlen и strcpy | Аргументы указателя не указывают на NULL - отключенная строка. | Поведение функции не определено. | Передайте NULL - отключенная строка к функциям обработки строк. |
Обработка файла функционирует в stdio.h такой как fputc и fread | FILE* аргумент указателя может иметь значение NULL . | Поведение функции не определено. | Протестируйте FILE* указатель для NULL перед использованием его как аргумент функции. |
Обработка файла функционирует в unistd.h такой как lseek и read | Аргумент дескриптора файла может быть-1. | Поведение функции не определено. Большинство реализаций | Протестируйте возвращаемое значение Если возвращаемое значение-1, проверяйте значение |
Аргумент дескриптора файла представляет закрытый дескриптор файла. | Поведение функции не определено. | Закройте дескриптор файла только после того, как вы полностью закончите использовать его. В качестве альтернативы вновь откройте дескриптор файла перед использованием его как аргумент функции. | |
Генерация имени каталога функционирует, такие как mkdtemp и mkstemps | Последними шестью символами шаблона строки не является XXXXXX . | Функция заменяет последние шесть символов на строку, которая делает имя файла уникальным. Если последними шестью символами не является XXXXXX , функция не может сгенерировать достаточно уникальное имя каталога. | Протестируйте, если последними шестью символами строки является XXXXXX перед использованием строки как аргумент функции. |
Функции, связанные с переменными окружения, такими как getenv и setenv | Аргументом строки является "" . | Поведение задано реализацией. | Протестируйте аргумент строки на "" перед использованием его как getenv или setenv аргумент. |
Аргумент строки завершает работу со знаком "равно", = . Например, "C=" вместо "C" . | Поведение задано реализацией. | Не отключайте аргумент строки с = . | |
Представьте в виде строки функции обработки, такие как strtok и strstr |
| Некоторые реализации не обрабатывают эти случаи ребра. | Протестируйте строку для "" перед использованием его как аргумент функции. |
Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Bug Finder в Пользовательском интерфейсе Рабочего стола Polyspace.
Смотрите примеры мер ниже.
Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
NULL
Указатель, пройден как strnlen
Аргумент#include <string.h>
#include <stdlib.h>
enum {
SIZE10 = 10,
SIZE20 = 20
};
int func() {
char* s = NULL;
return strnlen(s, SIZE20);
}
В этом примере, NULL
указатель передается как strnlen
аргумент вместо NULL
- отключенная строка.
Перед рабочим анализом кода задайте компилятор GNU. Смотрите Compiler (-compiler)
.
NULL
- отключенная СтрокаПередайте NULL
- отключенная строка в качестве первого аргумента strnlen
.
#include <string.h> #include <stdlib.h> enum { SIZE10 = 10, SIZE20 = 20 }; int func() { char* s = ""; return strnlen(s, SIZE20); }
Неподдерживаемые сложные аргументы происходят, когда эти функции вызваны с complex
аргумент:
atan2
erf
fdim
fmin
ilogb
llround
logb
nextafter
rint
tgamma
cbrt
erfc
floor
fmod
ldexp
log10
lrint
nexttoward
round
trunc
ceil
exp2
fma
frexp
lgamma
log1p
round
remainder
scalbn
copysign
expm1
fmax
hypot
llrint
log2
nearbyint
remquo
scalbln
Вызов любой из предыдущих функций с complex
аргумент является неопределенным поведением в стандарте C++, который может привести к неожиданным результатам. Поскольку некоторые математические функции поддерживают complex
аргументы, в то время как функции в предыдущем списке не делают, неожиданные результаты, могут затруднить отладку. Выполнение некоторых из этих математических операций на complex
номер не может быть математически звуковым, который указывает на проблему в базовой логике вашего кода.
Постарайтесь не вызывать предыдущие функции с complex
входной параметр. Чтобы выполнить предыдущие математические операции на комплексном числе, задайте альтернативные функции та поддержка complex
аргументы.
log2
и trunc
Функции со сложными аргументами#include <complex.h> #include <tgmath.h> typedef double complex cDouble; cDouble Noncompliant (void) { cDouble Z = 2.0 + 4.0 * I; cDouble result = log2 (Z); //Noncompliant return trunc(result);//Noncompliant }
В этом примере, функциональном Noncompliant
вычисляет основу два логарифма комплексного числа, обрезает результат и возвращает его. Функции log2
и trunc
не поддерживайте сложный аргумент. Polyspace® отмечает эти операции.
Одна возможная коррекция должна задать альтернативные функции та поддержка комплексные числа. Например, в то время как log2
не поддерживает complex
числа, функциональный log
делает. Задайте функциональный complexLog2
это использует log
вычислить основу два логарифма комплексного числа. Точно так же trunc
не поддерживает complex
числа и математическое правило для усечения комплексного числа не четко определены. Задайте функциональный complexTrunc
это обрезает комплексное число путем усечения его действительных и мнимых частей отдельно.
#include <complex.h> #include <tgmath.h> typedef double complex cDouble; cDouble complexLog2(cDouble z) { return log (z) / log (2); // Compliant } cDouble complexTrunc(cDouble z){ return trunc(creal(z)) + I*trunc(cimag(z)); //Compliant } cDouble Compliant (void) { cDouble Z = 2.0 + 4.0 * I; cDouble result = complexLog2 (Z); //Compliant return complexTrunc(result);//Compliant }
Несоответствие объявления функции происходит, когда прототип функции не совпадает со своим определением. Если функция испытывает недостаток в прототипе в файле, где это называется, Polyspace выводит свой прототип на основе подписи вызова. Если выведенный прототип не совпадает с определением функции, Polyspace повышает этот дефект. Прототип функции variadic не может быть выведен из своего вызова функции. Если вы вызываете variadic функцию, не задавая ее прототип в том же файле, Polyspace повышает этот дефект.
При выведении прототипа функции от вызова до такой функции Polyspace делает эти предположения:
Количество аргументов выведенного прототипа равно входному параметру вызова функции.
Типы аргумента выведенного прототипа установлены путем неявного продвижения типов аргумента вызова функции. Например, оба подписанных и char
без знака или
short
аргументам типа способствуют на int
. Так же float
аргументам типа способствуют на double
.
Несоответствие типов между аргументами функционального определения и прототипа функции может зависеть от вашей среды. Polyspace рассматривает два типа как совместимые, если у них есть тот же размер и со знаком в среде, которую вы используете. Например, если ваш задавать -target
как i386, Polyspace рассматривает long
и int
как совместимые типы.
Средство проверки не отмечает эту проблему в Polyspace по умолчанию как Вы Анализ кода. Смотрите Средства проверки, Деактивированные в Polyspace, когда Вы Кодируете Анализ По умолчанию (Polyspace Bug Finder Access).
Согласно стандарту C, несоответствие объявления функции может привести к неопределенному поведению даже при том, что такой код может скомпилировать успешно создание только предупреждения во время компиляции. Поскольку код с этой проблемой может скомпилировать успешно, несоответствия объявления функции могут привести к неожиданным результатам, которые затрудняют, чтобы диагностировать.
Прежде чем вы вызовете функцию, обеспечьте ее полный прототип, даже если вы задаете функцию позже в том же файле.
Избегайте любого несоответствия между аргументами номера в объявлении прототипа функции и функциональном определении.
Избегайте любого несоответствия между типами аргумента объявления прототипа функции и функционального определения.
Когда полные прототипы вызванных функций обеспечиваются, компилятор пытается разрешить любые несоответствия объявления функции через неявный кастинг. Если компилятору не удается разрешить несоответствие, сбои компиляции, который предотвращает неожиданное поведение. Чтобы зафиксировать такие ошибки компиляции, вызовите функции с помощью типов аргумента и чисел, которые совпадают с функциональным определением.
// file1.c void foo(int iVar){ //... } void bar(float fVar1, float fVar2){ //... } void bar2(float fVar1){ //... } void fubar(const char* str,...){ //... } void foo2(char cVar){ //... } void call_variadic(){ fubar("String"); } |
//file2.c void bar2(float); void foo2(int); void call_funcs(){ int iTemp; float fTemp; foo();//Noncompliant bar(fTemp,fTemp);//Noncompliant fubar("String"); //Noncompliant bar2(iTemp);//Compliant foo2(iTemp); //Noncompliant } |
В этом примере, функции foo
, foo2
панель
, bar2
, и fubar
заданы в файле file1.c
. Эти функции затем вызваны в файле file2.c
.
Функциональный foo
задан в file1.c
с одним int
введите и названный в file2.c
без любого входа. Поскольку file2.c
не имеет прототипа для foo
, Polyspace выводит прототип на основе вызова foo()
, который не берет входа. Этот выведенный прототип не совпадает с объявлением функции в file1.c
. Polyspace отмечает вызов.
Функциональный bar
задан в file1.c
с двумя float
входные параметры и названный в file2.c
с двумя float
входные параметры. Поскольку file2.c
не имеет прототипа для bar
, Polyspace выводит прототип на основе вызова bar(fTemp,fTemp)
. Путем продвижения типов аргумента вызова функции подписью этого выведенного прототипа является bar(double, double)
, который не совпадает с объявлением функции в file1.c
. Polyspace отмечает вызов.
Функциональный bar2
задан в file1.c
с одним float
входной параметр. Полный прототип для bar2
, то, которое совпадает с определением, обеспечивается в file2.c
. Поскольку полный прототип присутствует в этом файле, когда bar2
вызван неправильным входом, компилятор неявно преобразует int
вход iTemp
в float
. Поскольку вызов функции совпадает с объявлением после того, как неявное преобразование, упрощенное прототипом, Polyspace не отметит вызов.
Функциональный foo2
задан в file1.c
с char
входной параметр. Его прототип в file2.c
задан с int
входной параметр. Поскольку определение и прототип не соответствуют, Polyspace отмечает вызов foo2
.
variadic функционируют fubar
задан в file1.c
. Вызов его в call_variadic
совместимо, потому что вызов прибывает после определения. Функциональный fubar
не имеет прототипа в file2.c
. Поскольку функция берет переменное количество входных параметров, его прототип не может быть выведен. Вызов fubar
в file2.c
испытывает недостаток в прототипе, и Polyspace отмечает вызов.
Фиксация для этого дефекта должна объявить полные прототипы для вызванных функций во всех модулях компиляции. Это - лучшая практика объединить объявления прототипа функции в заголовочном файле, и затем включать его в файлы, где функции вызваны. В этом случае решите отмеченные вопросы включением такого заголовочного файла prototype.h
в file2.c
. Если правильный прототип объявляется, вызов foo()
в file2.c
вызывает отказ компиляции, потому что компилятор не может разрешить несоответствие между вызовом и заявленным прототипом. Вызовите foo
с int
разрешить отказ компиляции.
// file1.c void foo(int iVar){ //... } void bar(float fVar1, float fVar2){ //... } void bar2(float fVar1){ //... } void fubar(const char* str,...){ //... } void foo2(char cVar){ //... } void call_variadic(){ fubar("String"); } |
//prototypes.h void foo(int iVar); void bar(float fVar1, float fVar2); void fubar(const char* str,...); void bar2(float); void foo2(char); void call_variadic(void); void call_funcs(void); |
//file2.c #include"prototype.h" void call_funcs(){ int iTemp; float fTemp; //foo(); This call results in compile failure foo(iTemp);//Compliant bar(fTemp,fTemp);//Compliant fubar("String"); //Compliant bar2(iTemp);//Compliant foo2('a'); //Compliant } |
Группа: правило 03. Выражения (EXP) |
[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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.
Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.