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

Linux программирование в примерах - Роббинс Арнольд

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 171 172 173 174 175 176 177 178 179 ... 253
Перейти на страницу:

Этот код явно патологический, но он предназначен для иллюстрации нашей мысли: setjmp() и longjmp() могут вести к трудно обнаруживаемым утечкам памяти. Предположим, что f1() правильно вызвал free(). Было бы далеко неочевидно, что память никогда не будет освобождена. В более крупной и более реалистичной программе, в которой longjmp() мог быть вызван лишь посредством if, найти такую утечку становится даже еще труднее.

Таким образом, при наличии setjmp() и longjmp() динамическая память должна управляться посредством глобальных переменных, а у вас должен быть код, который обнаруживает вход через longjmp() (посредством проверки возвращаемого значения setjmp()). Такой код должен затем освободить динамически выделенную память, которая больше не нужна.

В-шестых, longjmp() и siglongjmp() не следует использовать из функций, зарегистрированных посредством atexit() (см. раздел 9.1.5.3 «Функции завершения»).

В-седьмых, setjmp() и longjmp() могут оказаться дорогими операциями на машинах с множеством регистров.

При наличии всех этих проблем вы должны строго рассмотреть дизайн своей программы. Если вам не нужно использовать setjmp() и longjmp(), то, может, стоит обойтись без их использования. Однако, если их использование является лучшим способом структурировать свою программу, продолжайте и используйте их, но делайте это осмотрительно.

12.6. Псевдослучайные числа

Многим приложениям нужны последовательности случайных чисел. Например, игровые программы, имитирующие бросание костей, раздачу карт или вращение барабанов игровой машины, нуждаются в возможности случайного выбора одного из возможных значений. (Подумайте о программе fortune, содержащей большую коллекцию афоризмов; каждый раз при запуске она «случайно» выдает новое высказывание.) Многие криптографические алгоритмы также требуют наличия случайных чисел «высокого качества». В данном разделе описываются различные способы получения последовательностей случайных чисел.

ЗАМЕЧАНИЕ. Природа случайности, генерация случайных чисел и их «качество» являются обширными темами, выходящими за рамки данной книги. Мы предоставляем введение в доступные функции API, но это все, что мы можем сделать Другие источники с более подробной информацией см в разделе 12.9 «Рекомендуемая литература»

Компьютеры по своему строению являются детерминистическими. Одно и то же вычисление с одними и теми же входными данными всегда должно давать одни и те же результаты. Соответственно, они не годятся для генерации истинно случайных чисел, то есть последовательностей чисел, в которых каждое число в последовательности полностью независимо от числа (или чисел), идущих перед ним. Вместо этого разновидности чисел, обычно используемых на программном уровне, называются псевдослучайными числами. То есть в любой данной последовательности номера выглядят независимыми друг от друга, но сама последовательность в целом повторяющаяся. (Эта повторяемость может быть ценным качеством; она обеспечивает детерминизм для программы в целом.)

Многие методы предоставления последовательностей псевдослучайных чисел работают посредством осуществления каждый раз одного и того же вычисления с начальным значением (seed). Сохраненное начальное значение затем обновляется для использования в следующий раз. API предоставляет способ указания нового начального значения. Каждое начальное значение дает одну и ту же последовательность псевдослучайных чисел, хотя различные начальные числа дают (должны давать) различные последовательности.

12.6.1. Стандартный С: rand() и srand()

Стандартный С определяет две связанные функции для псевдослучайных чисел.

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

int rand(void);

void srand(unsigned int seed);

rand() каждый раз после вызова возвращает псевдослучайное число в диапазоне от 0 до RAND_MAX (включительно, насколько мы можем судить по стандарту C99). Константа RAND_MAX должна быть по крайней мере 32 767; она может быть больше.

srand() дает генератору случайных чисел в качестве начального значения seed. Если srand() никогда не вызывался приложением, rand() ведет себя так, как если бы seed был равен 1.

Следующая программа, ch12-rand.c, использует rand() для вывода граней игральных костей.

1  /* ch12-rand.c --- генерирует игральные кости, используя rand(). */

2

3  #include <stdio.h>

4  #include <stdlib.h>

5

6  char *die_faces[] = { /* Управляет ASCII графика! */

7   "       ",

8   "   *   ", /* 1 */

9   "       ",

10

11  "       ",

12  " *   * ", /* 2 */

13  "       ",

14

15  "       ",

16  " * * * ", /* 3 */

17  "       ",

18

19  " *   * ",

20  "       ", /* 4 */

21  " *   * ",

22

23  " *   * ",

24  "   *   ", /* 5 */

25  " *    * ",

26

27  " * * * ",

28  "       ", /* 6 */

29  " * * * ",

30 };

1 ... 171 172 173 174 175 176 177 178 179 ... 253
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Роббинс Арнольд.
Комментарии