Предупреждения о слишком малых размерах массивов для функций в C / Stack Overflow

Существуют ли какие-либо инструменты (предпочтительно в linux), которые могут предупреждать, когда аргумент определяется как меньший массив, чем указывает прототип?

например:

void somefunc(float arg[10]);  /* normally this would be defined in a header */

void my_func(void)
{
float arg[2];
somefunc(arg);  /* <-- this could be a warning */
}

Я понимаю, что это не недействительный код, но он мог бы разрешить некоторые распространенные ошибки, если бы можно было предупредить об этом (недавно столкнулся с одной из этих ошибок).

Некоторые инструменты (например, clang static checker) будут предупреждать, если функция находится в том же файле и устанавливает значение вне границ массива, но мне было интересно, если что-нибудь предупредит, если arg меньше, чем один прототип.

Я использовал cppcheck, clang, smatch, splint, gcc’s -Wextra … но никто не жалуется на это.

2

Решение

Значение в прототипе не имеет значения для компилятора и игнорируется! Объявленная выше функция эквивалентна

void somefunc(float* arg);

а также

void somefunc(float arg[]);

При использовании C ++ вы можете справиться с ограничением размера во время компиляции, используя ссылки. Если вы действительно хотите иметь массив из 10 floats, вы можете передать его по ссылке, что обеспечит правильный размер:

void somefunc(float (&arg)[10]);

Однако это предотвратит передачу больших массивов. Вы можете поиграть с функцией пересылки шаблонов, если хотите передать большие массивы:

void somefunc_intern(float* arg);
template <int Size>
typename std::enable_if<(10 <= Size)>::type
somefunc(float (&arg)[Size]) {
somefunc_intern(arg);
}

Конечно, это не будет генерировать предупреждение, но будет ошибкой, если передан слишком маленький массив.

8

Другие решения

в С язык, float arg[10] Границы массива параметров являются просто стилистическими: это подсказка для программиста, а не для компилятора. Поскольку C имеет слабую проверку типов, вы можете передать любой указатель с плавающей точкой или массив в функцию. Кто-то может поспорить и сказать, что программист, который не читает документацию функции перед передачей ей параметров, напрашивается на неприятности. Но, конечно, всегда есть вероятность случайных ошибок.

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

Теоретически, вы могли бы написать код, который заставит компилятор выдавать больше предупреждений, но это запутает программу. Я не рекомендовал бы это, это было бы похоже на:

void somefunc(float (*arr_ptr)[10])
{
float* arg = *arr_ptr;
...
}

int main()
{
float ten[10];
float two[2];

somefunc(ten);  // warning
somefunc(&ten); // warning
somefunc(two);  // warning
somefunc(&two); // warning

float (*ten_ptr)[10] = &ten;
float (*two_ptr)[2] = &two;

somefunc(ten_ptr) // ok
somefunc(two_ptr) // warning

}
3

Задав этот вопрос, cppcheck добавил эту функцию в ответ на мое предложение (спасибо, ребята!),

Commit:
https://github.com/danmar/cppcheck/commit/7f6a10599bee61de0c7ee90054808de00b3ae92d

Выпуск:
http://sourceforge.net/apps/trac/cppcheck/ticket/4262

На момент написания статьи этого еще не было в выпуске, но я предполагаю, что это будет в следующем выпуске.

1

Совершенно обычный компилятор C ++ выдаст вам ошибку компиляции, если вы используете std::array<N> вместо или C массивов.

Так просто сделать это?

-1
По вопросам рекламы [email protected]