👀 📔 читать онлайн » Компьютеры и Интернет » Программирование » Linux программирование в примерах - Роббинс Арнольд

Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"

Перейти на страницу:

Операторы проверки особенно полезны для описания двух разновидностей инвариантов: предусловий и постусловий: условий, которые должны быть истинными соответственно перед и после исполнения сегмента кода. Простым примером предусловий и постусловий является линейный поиск:

/* lsearch --- возвратить индекс с данным значением в массиве или -1,

   если не найдено */

int lsearch(int *array, size_t size, int value) {

 size_t i;

 /* предусловие: array != NULL */

 /* предусловие: size > 0 */

 for (i = 0; i < size; i++)

  if (array[i] == value)

   return i;

 /* постусловие: i == size */

 return -1;

}

Этот пример определяет условия, используя комментарии. Но не было бы лучше проверить условия с использованием кода? Это является задачей макроса

assert()
:

#include <assert.h> /* ISO С */

void assert(/* <i>скалярное выражение</i> */);

Когда скалярное выражение ложно, макрос

assert()
выводит диагностическое сообщение и завершает программу (с помощью функции
abort()
; см. раздел 12.4 «Совершение самоубийства:
abort()
»).
ch12-assert.c
снова предоставляет функцию
lsearch()
, на этот раз с оператором проверки и функцией
main()
:

1  /* ch12-assert.с --- демонстрация операторов проверки */

2

3  #include &lt;stdio.h&gt;

4  #include &lt;assert.h&gt;

5

6  /* lsearch --- возвращает индекс с данным значением в массиве или -1, если не найдено */

7

8  int lsearch(int *array, size_t size, int value)

9  {

10  size_t i;

11

12  assert(array != NULL);

13  assert(size &gt; 0);

14  for (i = 0; i &lt; size; i++)

15   if (array[i] == value)

16    return i;

17

18  assert(i == size);

19

20  return -1;

21 }

22

23 /* main --- проверить наши условия */

24

25 int main(void)

26 {

27 #define NELEMS 4

28  static int array[NELEMS] = { 1, 17, 42, 91 };

29  int index;

30

31  index = lsearch(array, NELEMS, 21);

32  assert(index == -1);

33

34  index = lsearch(array, NELEMS, 17);

35  assert(index == 1);

36

37  index = lsearch(NULL, NELEMS, 10); /* won't return */

38

39  printf(&quot;index = %dn&quot;, index);

40

41  return 0;

42 }

После компиляции и запуска оператор проверки в строке 12 «выстреливает»:

$ <b>ch12-assert</b> /* Запуск программы */

ch12-assert: ch12-assert.c:12: lsearch: Assertion 'array != ((void *)0)' failed.

Aborted (core dumped)

Сообщение от

assert()
варьирует от системы к системе. Для GLIBC на GNU/Linux сообщение включает имя программы, имя файла с исходным кодом и номер строки, имя функции, а затем текст завершившегося неудачей условия. (В этом случае именованная константа
NULL
проявляется в виде своего макрорасширения '
((void*)0)'
.)

Сообщение '

Aborted (core dumped)
' означает, что
ch12-assert
создала файл
core
; т.е. снимок адресного пространства процесса непосредственно перед его завершением. [122] Этот файл может быть использован впоследствии с отладчиком; см. раздел 15.3 «Основы GDB». Создание файла
core
является намеренным побочным результатом
assert()
; предполагается, что произошла решительная ошибка, и вы хотите исследовать процесс с помощью отладчика для ее определения.

Вы можете отменить оператор проверки, компилируя свою программу с помощью опции командной строки '

-DNDEBUG
'. Когда этот макрос определен до включения
&lt;assert.h&gt;
, макрос
assert()
расширяется в код, который ничего не делает. Например:

$ <b>gcc -DNDEBUG=1 ch12-assert.c -о ch12-assert</b> /* Компиляция с -DNDEBUG */

$ <b>ch12-assert</b> /* Запуск */

Segmentation fault (core dumped) /* Что случилось? */

Здесь мы получили настоящий дамп ядра! Мы знаем, что операторы проверки были запрещены; сообщения «failed assertion» нет. Что же случилось? Рассмотрите строку 15

lsearch()
при вызове из строки 37
main()
. В этом случае переменная
array
равна
NULL
. Доступ к памяти через указатель
NULL
является ошибкой. (Технически различные стандарты оставляют «неопределенным» то, что происходит при разыменовывании указателя
NULL
. Наиболее современные системы делают то же, что и GNU/Linux; они завершают процесс, посылая ему сигнал
SIGSEGV
; это, в свою очередь, создает дамп ядра. Этот процесс описан в главе 10 «Сигналы».

Перейти на страницу:
Оставить комментарий о книге
Подтвердите что вы не робот:*

Отзывы о книге "Linux программирование в примерах, автор: Роббинс Арнольд":

Все материалы на сайте размещаются его пользователями. Администратор сайта не несёт ответственности за действия пользователей сайта. Вы можете направить вашу жалобу на почту booksreadonlinecom@gmail.com
© 2021 - 2026 booksread-online.com