Книга: Основы программирования в Linux
Lint удаление ошибок из ваших программ
Lint удаление ошибок из ваших программ
Первые системы UNIX предоставляли утилиту lint
. Эта программа по существу — препроцессор компилятора С со вставленными тестами, обеспечивающими некоторые проверки с точки зрения здравого смысла и вывод предупреждений. Среди прочего она обнаруживает случаи применения переменных до того, как им было присвоено значение, или случаи неиспользования аргументов функций.
Более современные компиляторы C могут ценой производительности времени компиляции формировать аналогичные предупреждения. Утилиту lint
, как таковую, обогнала стандартизация языка С. Поскольку средство основывалось на раннем компиляторе С, оно совсем не справляется с синтаксисом ANSI. Есть несколько коммерческих версий lint
для UNIX и одна версия в Интернете для Linux, названная splint
. Она известна под именем LClint, как часть проекта MIT (Massachusetts Institute of Technology, Массачусетский технологический институт), занимающегося разработкой средств формального описания. splint
, средство подобное lint
, может предоставлять полезные обзорные комментарии к программному коду. Найти splint
можно по адресу http://www.splint.org.
Далее приведена первоначальная версия (debug0.c) программы-примера, которую вы уже отладили.
/* 1 */ typedef struct {
/* 2 */ char *data;
/* 3 */ int key;
/* 4 */ } item;
/* 5 */
/* 6 */ item array[j] = {
/* 7 */ {"bill", 3},
/* 8 */ {"neil", 4},
/* 9 */ {"john", 2},
/* 10 */ {"rick", 5},
/* 11 */ {"alex", 1},
/* 12 */ };
/* 13 */
/* 14 */ sort(a, n)
/* 15 */ item *a;
/* 16 */ {
/* 17 */ int i = 0, j = 0;
/* 18 */ int s;
/* 19 */
/* 20 */ for(; i < n & s != 0; i++) {
/* 21 */ s = 0;
/* 22 */ for(j = 0; j < n; j++) {
/* 23 */ if(a[j].key > a[j+1].key) {
/* 24 */ item t = a[j];
/* 25 */ a[j] = a[j+1];
/* 26 */ a[j+1] = t;
/* 27 */ s++;
/* 28 */ }
/* 29 */ }
/* 30 */ n--;
/* 31 */ }
/* 32 */ }
/* 33 */
/* 34 */ main()
/* 35 */ {
/* 36 */ sort(array,5);
/* 37 */ }
В этой версии есть проблема в строке 20, где вместо предполагаемого оператора &&
применяется оператор &
. Далее приведен отредактированный пример вывода splint
, выполненной с этой версией программы. Обратите внимание на то, как она обнаруживает проблемы в строке 20 — тот факт, что вы не инициализировали переменную s и что возможны проблемы с условием из-за некорректного оператора.
neil@susel03:~/BLP4e/chapter10> splint -strict debug0.c
Splint 3.1.1 --- 19 Mar 2005
debug0.c:7:18: Read-only string literal storage used as initial value for
unqualified storage: array[0].data = "bill"
A read-only string literal is assigned to a non-observer reference. (Use -readonlytrans to inhibit warning)
debug0.c:8:18: Read-only string literal storage used as initial value for
unqualified storage: array[1].data = "neil"
debug0.c:9:18: Read-only string literal storage used as initial value for
unqualified storage: array[2].data = "john"
debug0.с:10:18: Read-only string literal storage used as initial value for
unqualified storage: array[3].data = "rick"
debug0.c:11:18: Read-only string literal storage used as initial value for
unqualified storage: array[4].data = "alex"
debug0.с:14:22: Old style function declaration
Function definition is in old style syntax. Standard prototype syntax is
preferred. (Use -oldstyle to inhibit warning)
debug0.с: (in function sort)
debug0.c:20:31: Variable s used before definition
An rvalue is used that may not be initialized to a value on some execution
path. (Use -usedef to inhibit warning)
debug0.с:20:23: Left operand of & is not unsigned value (boolean):
i < n & s != 0
An operand to a bitwise operator is not an unsigned values. This may have
unexpected results depending on the signed representations. (Use
-bitwisesigned to inhibit warning).
debug0.c:20:23: Test expression for for not boolean, type unsigned int:
i < n & s != 0
Test expression type is not boolean or int. (Use -predboolint to inhibit
warning);
debug0.с:25:41: Undocumented modification of a[]: a[j] = a[j + 1]
An externally-visible object is modified by a function with no /*@modifies@*/
comment. The /*@modifies ... @*/ control comment can be used to give a
modifies list for an unspecified function. (Use -modnomods to inhibit
warning)
debug0.c:26:41: Undocumented modification of a[]: a[j + 1] = t
debug0.c:20:23: Operands of & are non-integer (boolean) (in post loop test):
i < n & s != 0
A primitive operation does not type check strictly. (Use -strictops to
inhibit warning)
debug0.с:32:14: Path with no return in function declared to return int
There is a path through a function declared to return a value on which there
is no return statement. This means the execution may fall through without
returning a meaningful result to the caller. (Use -noret to inhibit
warning)
debug0.с:34:13: Function main declared without parameter list
A function declaration does not have a parameter list. (Use -noparams
to inhibit warning)
debug0.с: (in function main)
debug0.с:36:22: Undocumented use of global array
A checked global variable is used in the function, but not listed in its
globals clause. By default, only globals specified in .lcl files are
checked.
To check all globals, use +allglobals. To check globals selectively use
/*@checked@*/ in the global declaration. (Use -globs to inhibit warning)
debug0.с:36:17: Undetected modification possible from call to unconstrained
function sort: sort
An unconstrained function is called in a function body where
modifications are checked. Since the unconstrained function may modify
anything, there may be undetected modifications in the checked function.
(Use -modunconnomods to inhibit warning)
debug0.c:36:17: Return value (type int) ignored: sort(array, 5)
Result returned by function call is not used. If this is intended, can
cast result to (void) to eliminate message. (Use -retvalint to inhibit
warning)
debug0.c:37:14: Path with no return in function declared to return int
debug0.c:6:18: Variable exported but not used outside debug0: array
A declaration is exported, but not used outside this module. Declaration
can use static qualifier. (Use -exportlocal to inhibit warning)
debug0.c:14:13: Function exported but not used outside debug0: sort
debug0.c:15:17: Definition of sort
debug0.c:6:18: Variable array exported but not declared in header file
A variable declaration is exported, but does not appear in a header
file. (Used with exportheader.) (Use -exportheadervar to inhibit warning)
debug0.c:14:13: Function sort exported but not declared in header file
A declaration is exported, but does not appear in a header file. (Use
-exportheader to inhibit warning)
debug0.c:15:17: Definition of sort
Finished checking - 22 code warnings
$
Утилита выражает неудовольствие по поводу объявления функций в старом стиле (не ANSI) и несоответствия типов значений, возвращаемых функциями, и самими величинами, которые они возвращают (или нет) в действительности. Эти предупреждения не влияют на работу программы, но должны быть выведены.
Она также обнаружила две реальные ошибки в следующем фрагменте кода:
/* 18 */ int s;
/* 19 */
/* 20 */ for(; i < n & s != 0; i++) {
/* 21 */ s = 0;
Средство splint определило (выделенные цветом строки предыдущего вывода), что переменная s используется в строке 20, но не была при этом инициализирована, и что оператор &
стоит на месте более обычного оператора &&.
В данном случае старшинство оператора изменяет значение условия и создает проблему в программе.
Обе эти ошибки были исправлены при чтении исходного текста программы до запуска процесса отладки. Несмотря на то, что пример мало изобретателен и служит только для демонстрации, подобные ошибки регулярно возникают в реальных программах."
- 8.2. Языки программирования Виды программирований
- 1.1. Введение в объектно-ориентированное программирование
- 11.2. СВОЙСТВА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
- Перехват ошибок
- СТРУКТУРА ПРОСТОЙ ПРОГРАММЫ
- Обработка перехваченных ошибок
- ПРИМЕР ПРОСТОЙ ПРОГРАММЫ НА ЯЗЫКЕ СИ
- 6.2. Типичные ошибки при проведении программ продвижения и варианты их устранения
- Системное программное обеспечение
- Язык программирования Python
- 1.2.5. Пример программы
- 24.7. Использование программы-твикера