Функции вызова с правильным номером и типом аргументов
Функции вызова с правильным номером и типом аргументов.[1]
Эта проверка проверяет на наличие следующих проблем:
Неправильный режим доступа к файлам или состояние.
Ненадежное приведение указателя на функцию.
Стандартный вызов функции с неправильными аргументами.
Несоответствие объявления функции
Плохой режим доступа к файлам или состояние происходит, когда вы используете функции в 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. |
The | Пройдите или O_APPEND|O_WRONLY или O_APPEND|O_RDWR как режим доступа. |
Вы передаете флаги состояния O_APPEND и O_TRUNC вместе с open функция. |
The | В зависимости от того, что вы намерены сделать, передайте один из двух режимов. |
Вы передаете флаг состояния O_ASYNC на open функция. | В некоторых реализациях режим O_ASYNC не включает операции ввода-вывода, управляемые сигналом. | Используйте fcntl(pathname, F_SETFL, O_ASYNC); вместо этого. |
Исправление зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Вы можете реализовать исправление на любом событии в последовательности. Если сведения о результате не отображают историю событий, можно отследить их с помощью опций правого щелчка в исходном коде и просмотреть предыдущие связанные события. Смотрите также Результаты интерпретации Bug Finder в интерфейсе пользователя Polyspace Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты 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-terminated string. | Поведение функции не определено. | Передайте NULL-terminated string to string mandipulation functions. |
Функции обработки файлов в stdio.h такие как fputc и fread | The 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 Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.
NULL Указатель прошел как strnlen Аргумент#include <string.h>
#include <stdlib.h>
enum {
SIZE10 = 10,
SIZE20 = 20
};
int func() {
char* s = NULL;
return strnlen(s, SIZE20);
}
В этом примере a NULL указатель передается следующим strnlen аргумент вместо NULL-terminated string.
Перед выполнением анализа кода укажите компилятор 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);
}
Примечание
В коде С++ эта проверка применяется к функциям, которые заданы как extern "C".
Несоответствие объявления функции происходит, когда прототип extern "C" функция не соответствует ее определению. Несоответствие типов аргументов определения функции и прототипа функции может зависеть от вашего окружения. Polyspace® рассматривает два типа как совместимые, если они имеют одинаковый размер и сигнальность в окружении, которую вы используете. Например, если вы задаете -target как i386, Polyspace рассматривает long и int как совместимые типы.
В C++, если функция не задана как extern "C" и его прототип не соответствует никакому определению функции, компилятор обрабатывает прототип как образец неопределенной перегрузки функции. Polyspace не помечает вызовы таких неопределенных функций.
Чекер не помечает эту проблему в Polyspace по умолчанию во время анализа You Code. Смотрите Checkers Deactivated in Polyspace как You Code Default Analysis (Polyspace Bug Finder Access).
Несоответствие объявления функции может привести к неопределенному поведению. Когда объявления функций заданы как extern "C"несоответствия между определением и объявлением функции могут вызывать только предупреждения во время компиляции, в результате чего код компилируется, но ведет себя неожиданным образом.
Прежде чем вы вызовете функцию, предоставьте ее полный прототип, даже если вы задаете функцию позже в том же файле.
Избегайте любого несоответствия между числовыми аргументами в объявлении прототипа функции и определении функции.
Избегайте любого несоответствия между типами аргументов объявления прототипа функции и определением функции.
// file1.c
extern "C" void foo(int iVar){
//...
}
extern "C" void bar(int iVar){
//...
}
extern "C" void fubar(int A, ...){
//...
}
|
//prototype.h extern "C" void foo(void); extern "C" void fubar(int A, ...); extern "C" void bar(long iVar); |
//file2.c
//file2.c
#include"prototype.h"
void call_funcs(){
int iTemp;
float fTemp;
long lTemp;
foo(); //Noncompliant
bar(lTemp);//Noncompliant in x86_64
fubar(iTemp,fTemp);//Compliant
} |
В этом примере функции foo, bar, и fubar определяются в файле file1.c. Их прототипы заявлены в prototype.h. Затем эти функции вызываются в файле file2.c.
Функция foo определяется как int аргумент, но его прототип объявлен без какого-либо аргумента. Из-за этого несоответствия Polyspace помечает вызов функции.
Функция bar определяется как int аргумент, но его прототип объявлен с long аргумент. Эти два типа несовместимы с x86_64 окружение. Когда вы задаете -target как x86_64, Polyspace помечает вызов функции.
Вызов вариадной функции fubar является совместимым, поскольку его сигнатура вызова, прототип и определение совпадают.
Исправление этого дефекта состоит в том, чтобы объявить полные и точные прототипы для вызываемых функций. В этом случае исправьте возникшие проблемы, разрешив несоответствия между определением функции и объявлением прототипа. Обновите вызовы функций так, чтобы они совпадали с обновленными прототипами.
// file1.c
extern "C" void foo(int iVar){
//...
}
extern "C" void bar(int iVar){
//...
}
extern "C" void fubar(int A, ...){
//...
}
|
//prototype.h extern "C" void foo(int); extern "C" void fubar(int A, ...); extern "C" void bar(int iVar); |
//file2.c
//file2.c
#include"prototype.h"
void call_funcs(){
int iTemp;
float fTemp;
long lTemp;
foo(iTemp); //Compliant
bar(iTemp);//Compliant in x86_64
fubar(iTemp,fTemp);//Compliant
} |
| Группа: 02. Выражения (EXP) |
[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.
ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.
Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.