Ctrace(1)
Используя команду ctrace(1), можно проследить выполнение C-программы по операторам. ctrace читает исходный текст программы из файла и добавляет в него операторы печати для вывода значений переменных после каждого выполненного оператора. Результат выполнения команды следует направить во временный .c-файл, который затем использовать как входной для команды cc. Во время выполнения полученного в разультате файла a.out будет генерироваться вывод, в котором содержится много полезной информации о событиях в Вашей программе.
С помощью опций команды ctrace можно ограничить количество итераций при выполнении циклов. В исходный текст программы можно вставить функции, включающие и выключающие трассировку. Таким образом можно организовать трассировку только необходимых участков программы.
При обращении к ctrace можно указать только один файл с C-программой. Поэтому, чтобы проиллюстрировать действие ctrace на нашем примере, необходимо выполнить следующие команды:
ctrace restate.c > ct1.c ctrace oppty.c > ct2.c ctrace pft.c > ct3.c ctrace rfe.c > ct4.c
Здесь имена выходных файлов выбраны совершенно произвольно. Можно использовать любые подходящие имена. Выбранные имена файлов должны оканчиваться на .c, поскольку эти файлы будут использоваться как входные для системы компиляции языка C:
cc -o ctt ct1.c ct2.c ct3.c ct4.c
Затем команда
ctt -opr
выдаст приведенный ниже результат на стандартный вывод (stdout). (Напомним, что программа читает исходные данные из файла info.) Разумеется, этот результат можно направить в какой-нибудь файл или вывести на печать для последующей обработки или изучения.
9 main (argc, argv) 24 if (argc < 2) /* argc == 2 */ 32 opterr = FALSE; /* FALSE == 0 */ /* opterr == 0 */ 34 while ((ch = getopt (argc, argv, "opr")) != EOF) /* argc == 2 */ /* argv == 2147483384 */ /* ch == 111 or 'o' */ { 35 switch (ch) /* ch == 111 or 'o' */ 36 case 'o': 37 oflag = TRUE; /* TRUE == 1 */ /* oflag == 1 */ 38 break; 50 }
34 while ((ch = getopt (argc, argv, "opr")) != EOF) /* argc == 2 */ /* argv == 2147483384 */ /* ch == 112 or 'p' */ { 35 switch (ch) /* ch == 112 or 'p' */ 39 case 'p': 40 pflag = TRUE; /* TRUE == 1 */ /* pflag == 1 */ 41 break; 50 }
34 while ((ch = getopt (argc, argv, "opr")) != EOF) /* argc == 2 */ /* argv == 2147483384 */ /* ch == 114 or 'r' */ { 35 switch (ch) /* ch == 114 or 'r' */ 42 case 'r': 43 rflag = TRUE; /* TRUE == 1 */ /* rflag == 1 */ 44 break; 50 }
34 while ((ch = getopt (argc, argv, "opr")) != EOF) /* argc == 2 */ /* argv == 2147483384 */ /* ch == -1 */ 52 if ((fin = fopen ("info", "r")) == NULL) /* fin == 1052602 */ 59 if (fscanf (fin, "%s%f%f%f%f%f%f", first.pname, &first.ppx, &first.dp, &first.i, &first.c, &first.t, &first.spx) != 7) /* fin == 1052602 */ /* first.pname == 2147483294 */ 68 printf ("Наименование: %s\n", first.pname); /* first.pname == 2147483294 or "Tutti_Frutti" */ Наименование: Tutti_Frutti
70 if (oflag) /* oflag == 1 */ 71 printf ("Приемлемая цена: $%#5.2f\n", oppty (&first)); 5 oppty (ps) 8 return (ps->i/12 * ps->t * ps->dp); /* ps->i == 1074108825 */ /* ps->t == 1073741824 */ /* ps->dp == 1074339512 */ Приемлемая цена: $4321.00
73 if (pflag) /* pflag == 1 */ 74 printf ("Ожидаемая прибыль (потери): $%#7.2f\n", pft (&first)); 5 pft (ps) 8 return (ps->spx - ps->ppx + ps->c); /* ps->spx == 1076101120 */ /* ps->ppx == 1072693248 */ /* ps->c == 1073259479 */ Ожидаемая прибыль (потери): $12345.00
77 if (rflag) /* rflag == 1 */ 78 printf("Фондоотдача: %#3.2f%%\n", rfe (&first)); 5 rfe (ps) 8 return (100 * (ps->spx - ps->c) / ps->spx); /* ps->spx == 1076101120 */ /* ps->c == 1073259479 */ Фондоотдача: 95.00%
/* return */
Используя в качестве примера правильно работающую программу, трудно продемонстрировать возможности ctrace. Интереснее было бы обнаружить с помощью ctrace ошибку. По-видимому, эта утилита наиболее полезна в случае, когда программа выполняется до конца, но ее результат не совпадает с ожидаемым.