Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

Этот случай поднимает важный момент относительно операторов проверки. Часто программисты ошибочно используют операторы проверки вместо проверки ошибок времени исполнения. В нашем случае тест '

array != NULL
' должен был быть проверкой времени исполнения:

if (array == NULL) return -1;

Тест '

size > 0
' (строка 13) менее проблематичен; если
size
равен 0 или меньше 0, цикл никогда не исполнится, и
lsearch
(правильно) возвратит -1. (По правде, этот оператор проверки не нужен, поскольку код правильно обрабатывает случай '
size <= 0
'.)

Логика,

стоящая за отменой оператора проверки, заключается в том, что дополнительные проверки могут снизить производительность программы и поэтому должны быть запрещены в заключительной версии программы. Хоар [123] , однако, сделал такое замечание:

«В конце концов, абсурдно делать тщательные проверки безопасности при отладочных запусках, когда к результатам нет никакого доверия, а затем удалять их из финальных версий, когда ошибочный результат может быть дорогим или катастрофическим. Что бы мы подумали об энтузиасте-мореплавателе, который надевает свой спасательный жилет при тренировке на сухой земле и снимает его, как только выходит в море?»

123

Hints On Programming Language Design, C.A.R. Hoare Stanford University Computer Science Technical Report CS-73-403 (

ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/73/403/CS-TR-73-403.pdf
). December, 1973 — Примеч. автора.

С такими мнениями, наша рекомендация заключается во внимательном использовании операторов проверки- во-первых, для любого данного оператора проверки рассмотрите возможность использования вместо него проверки времени исполнения. Во-вторых, тщательно разместите свой оператор проверки, чтобы не было возражений против их оставления на своем месте лаже в финальной версии вашей программы.

Наконец, отметим следующее из раздела «Ошибки» справочной страницы GNU/Linux assert(3):

assert
реализован как макрос: если у проверяемого выражения есть побочные результаты, поведение программы может меняться в зависимости от того, определен ли
NDEBUG
. Это может создавать гейзенберговские ошибки, которые исчезают при отключении режима отладки.

Знаменитый принцип неопределенности Гейзенберга из физики указывает, что чем более точно вы определите скорость частицы, тем менее точно вы определите ее положение, и наоборот. В терминах непрофессионала это означает что простой факт наблюдения частицы влияет на нее.

Сходное явление совершается в программировании, не связанном с физикой частиц: действие компилирования программы для отладки или запуска ее а режиме отладки может изменить поведение программы. В частности, первоначальная ошибка может исчезнуть. Такие ошибки в разговоре называют гейзенберговскими.

Справочная страница предостерегает нас от использования при вызовах

assert
выражений с побочными эффектами:

assert(*p++ == '\n');

Здесь побочным эффектом является увеличение указателя p как часть теста. Когда определен

NDEBUG
, аргумент выражения исчезает из исходного кода; он никогда не исполняется. Это может привести к неожиданной неудаче. Однако, как только при подготовке к отладке запрет на операторы проверки отменяется, все начинает снова работать! Такие проблемы трудно
отследить.

12.2. Низкоуровневая память: функции

memXXX

Несколько функций предоставляют возможность для работы с произвольными блоками памяти низкоуровневые службы. Все их имена начинаются с префикса '

mem
':

#include <string.h> /* ISO C */

void *memset(void *buf, int val, size_t count);

void *memcpy(void *dest, const void *src, size_t count);

void *memmove(void *dest, const void *src, size_t count);

void *memccpy(void *dest, const void *src, int val, size_t count);

int memcmp(const void *buf1, const void *buf2, size_t count);

void *memchr(const void *buf, int val, size_t count);

12.2.1. Заполнение памяти:

memset

Функция

memset
копирует значение val (интерпретируемое как
unsigned char
) в первые
count
байтов буфера
buf
. Она особенно полезна для обнуления блоков динамической памяти:

void *p = malloc(count);

if (p != NULL)

 memset(p, 0, count);

Однако

memset
может использоваться с любой разновидностью памяти, не только с динамической. Возвращаемым значением является первый аргумент:
buf
.

12.2.2. Копирование памяти:

memcpy
,
memmove
и
memccpy

Три функции копируют один блок памяти в другой. Первые две функции отличаются в обработке перекрывающихся областей памяти; третья копирует память, но останавливается при встрече с определенным значением.

void *memcpy(void *dest, const void *src, size_t count)

Это простейшая функция. Она копирует

count
байтов из
src
в
dest
. Она не обрабатывает перекрывающиеся области памяти. Функция возвращает
dest
.

void *memmove(void *dest, const void *src, size_t count)

Подобно

memcpy
, она также копирует
count
байтов из
src
в
dest
. Однако, она обрабатывает перекрывающиеся области памяти. Функция возвращает
dest
.

void *memccpy(void *dest, const void *src, int val, size_t count)

Эта копирует байты из

src
в
dest
, останавливаясь либо после копирования
val
в
dest
, либо после копирования
count
байтов. Если она находит
val
, то возвращает указатель на положение в
dest
сразу за
val
. В противном случае возвращается
NULL
.

Теперь, в чем проблема с перекрывающейся памятью? Рассмотрим рис. 12.1.

Поделиться:
Популярные книги

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Душелов. Том 3

Faded Emory
3. Внутренние демоны
Фантастика:
альтернативная история
аниме
фэнтези
ранобэ
хентай
5.00
рейтинг книги
Душелов. Том 3

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5