Выбрать главу

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