Существуют ли какие-либо инструменты (предпочтительно в 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 … но никто не жалуется на это.
Значение в прототипе не имеет значения для компилятора и игнорируется! Объявленная выше функция эквивалентна
void somefunc(float* arg);
а также
void somefunc(float arg[]);
При использовании C ++ вы можете справиться с ограничением размера во время компиляции, используя ссылки. Если вы действительно хотите иметь массив из 10 float
s, вы можете передать его по ссылке, что обеспечит правильный размер:
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);
}
Конечно, это не будет генерировать предупреждение, но будет ошибкой, если передан слишком маленький массив.
в С язык, 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
}
Задав этот вопрос, cppcheck добавил эту функцию в ответ на мое предложение (спасибо, ребята!),
Commit:
https://github.com/danmar/cppcheck/commit/7f6a10599bee61de0c7ee90054808de00b3ae92d
Выпуск:
http://sourceforge.net/apps/trac/cppcheck/ticket/4262
На момент написания статьи этого еще не было в выпуске, но я предполагаю, что это будет в следующем выпуске.
Совершенно обычный компилятор C ++ выдаст вам ошибку компиляции, если вы используете std::array<N>
вместо или C массивов.
Так просто сделать это?