Программа prof(и ее эквивалент в проекте GNU, gprof) выводит отчёт из файла трассировки выполнения, который формируется во время выполнения профилируемой программы. Профилируемый исполняемый файл создается с помощью флага компилятора -p(для prof) или флага -pg(для gprof).
$ cc -pg -о program program.с
Программа компонуется со специальной библиотекой С, и в нее включается контрольный код. В конкретных системах он может отличаться, но общая цель — такая организация программы, которая позволяет часто прерывать выполнение и записывать этап выполнения. Контрольные данные записываются в файл mon.out (gmon.out для gprof) в текущем каталоге.
$ ./program
$ ls -ls
2 -rw-r--r-- 1 neil users 1294 Feb 4 11:48 gmon.out
Программа prof/gprof читает эти контрольные данные и выводит отчет. См. подробности, касающиеся опций программы, в интерактивном справочном руководстве. Далее в качестве примера приведен вывод (сокращенный) программы gprof.
cumulative self self total
time seconds seconds calls ms/call ms/call name
18.5 0.10 0.10 8664 0.01 0.03 doscan [4]
18.5 0.20 0.10 mcount (60)
14.8 0.28 0.08 43320 0.00 0.00 _number [5]
9.3 0.33 0.05 8664 0.01 0.01 _format_arg [6]
7.4 0.37 0.04 112632 0.00 0.00 _ungetc [8]
7.4 0.41 0.04 8757 0.00 0.00 _memccpy [9]
7.4 0.45 0.04 1 40.00 390.02 _main [2]
3.7 0.47 0.02 53 0.38 0.38 _read [12]
3.7 0.49 0.02 w4str [10]
1.9 0.50 0.01 26034 0.00 0.00 _strlen [16]
1.9 0.51 0.01 8664 0.00 0.00 strncmp [17]
Проверки соблюдения условий
Несмотря на то, что вставка на этапе разработки программы с помощью условной компиляции отладочного кода, такого как вызовы printf, распространена, иногда оставлять такие сообщения в поставляемой программе непрактично. Но часто проблемы возникают во время работы программы из-за некорректных допущений или исходных данных, а не из-за ошибок кодирования. Это события, которых "не может быть никогда". Например, функция может быть написана в расчете на то, что ее входные параметры будут в определенном диапазоне. Если передать ей некорректные данные, она может сделать некорректной работу всей системы.
В тех случаях, когда внутренняя логика системы нуждается в подкреплении, X/Open предоставляет макрос assert, применяемый для проверки правильности исходных данных и остановки выполнения программы в противном случае.
#include
void assert(int expression)
Макрос assertвычисляет выражение и, если оно не равно нулю, выводит некоторую диагностическую информацию о стандартной ошибке и вызывает функцию abortдля завершения программы.
Заголовочный файл assert.h определяет макросы в зависимости от определения флага NDEBUG. Если NDEBUGопределен во время обработки заголовочного файла, assertопределяется по существу как ничто. Это означает, что вы можете отключить проверки заданных выражений во время компиляции, компилируя с опцией -DNDEBUGили вставив перед включением файла assert.h строку
#define NDEBUG
в каждый исходный файл.
Этот метод применения порождает проблему. Если вы используете assertво время тестирования, но отключите макрос в рабочем коде, в вашем рабочем коде может оказаться менее строгая проверка, чем применявшаяся в процессе его тестирования. Обычно макросы assertне оставляют включенными в рабочем коде — вряд ли вам понравится рабочий код, предоставляющий пользователю недружелюбное сообщение assert failedи останавливающий программу. Быть может, лучше написать свою отслеживающую ошибки подпрограмму, которая проверяет выражение, использовавшееся в макросе, но не нуждается в полном отключении в рабочем коде.
Вы также должны убедиться в том, что у выражения макроса assertнет побочных эффектов. Например, если вы применяете вызов функции с побочным эффектом, этот побочный эффект не проявится в рабочем коде с отключенными макросами assert.
Выполните упражнение 10.2.
Упражнение 10.2. Программа assert.c.
Далее приведена программа assert.c, определяющая функцию, которая должна принимать положительное значение. Она защищает от ввода некорректного аргумента благодаря применению макроса assert.
После включения заголовочного файла assert.h и функции "квадратный корень", проверяющей положительное значение параметра, вы можете писать функцию main.
#include
#include
#include
#include
double my_sqrt(double x) {
assert(x >= 0.0);
return sqrt(x);
}
Читать дальше