Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

Глава 12. Разные дополнительные системные вызовы и библиотечные процедуры

12.1. Введение

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

12.2. Управление динамическим распределением памяти

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

var

x, у: something;

z: ^something;

a: array [0..19] of something;

Другими словами, расположение данных в наших примерах определялось во время компиляции. Однако многие вычислительные задачи удобнее решать при помощи динамического создания и уничтожения структур данных, а это значит, что расположение данных в программе определяется окончательно только во время выполнения программы. Семейство библиотечных функций ОС UNIX malloc (от memory allocation – выделение памяти) позволяет создавать объекты в области динамической памяти на стадии выполнения программы, которая в англоязычной литературе часто называется heap – «куча», «кипа» (книг). Функция malloc определяется следующим образом:

Описание

uses stdio;

function malloc(nbytes:longint):pointer;

В результате этого вызова функция malloc обычно возвращает указатель на участок памяти размером nbytes. При этом программа получает указатель на массив байтов, которые она может использовать по своему усмотрению. Если памяти недостаточно и система не может выделить запрошенный вызовом malloc объем памяти, то вызов возвращает нулевой указатель.

Обычно вызов malloc используется для выделения памяти под одну или несколько структур данных, например:

var

p:^item;

р := malloc(sizeof(item));

В случае успеха вызов malloc создает новую структуру item, на которую ссылается указатель р. Заметим, что возвращаемое вызовом malloc значение приводится к соответствующему типу указателя. Это помогает избежать вывода предупреждений компилятором или такими программами, как lint. Приведение типа в данном случае целесообразно, поскольку вызов malloc реализован так, чтобы отводить память под объекты любого типа при условии, что запрашивается достаточный для хранения объекта ее объем. Такие задачи, как выравнивание по границе слова, решаются самим алгоритмом функции malloc. Обратите внимание на то, что размер структуры item задается при помощи конструкции sizeof, которая возвращает размер объекта в байтах.

Функция free противоположна по своему действию функции malloc и возвращает отведенную память, позволяя использовать ее повторно. Функции free передается указатель, который был получен во время вызова malloc:

var

ptr:^item;

.

.

.

ptr := malloc(sizeof(item));

(* Выполнить какие-либо действия .. *)

free(ptr);

После подобного вызова функции free освобожденный участок памяти, на который указывает ptr, уже нельзя использовать, так как функция malloc может позднее снова его отдать процессу (целиком или частично). Очень важно, чтобы, функции free передавался указатель, который был получен от функции malloc, или от одной из функций calloc и realloc, принадлежащих тому же семейству. Если указатель не удовлетворяет этому требованию, то почти наверняка возникнут ошибки в механизме распределения динамической памяти, которые приведут к некорректной работе программы или к ее аварийному завершению. Неправильное применение функции free – очень часто встречающаяся и трудноуловимая ошибка.1

Еще две функции в семействе malloc непосредственно связаны с выделением памяти. Первой из них является функция calloc.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal