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

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

Жанры

Основы программирования в Linux
Шрифт:

}

Вы получите следующий результат:

$ ./memory5b

Segmentation fault

В этот раз вы пытаетесь прочесть непосредственно из нулевого адреса. Между вами и ядром теперь нет GNU-библиотеки libc, и программа прекращает выполнение. Имейте в виду, что некоторые системы UNIX разрешают читать из нулевого адреса, ОС Linux этого не допускает.

Освобождение памяти

До сих пор мы выделяли память и затем надеялись на то, что по завершении программы использованная нами память не будет потеряна, К счастью, система управления памятью в ОС Linux вполне способна с высокой

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

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

malloc
с помощью вызова
free
. Это позволяет выделить блоки, нуждающиеся в повторном объединении, и дает возможность библиотеке
malloc
следить за памятью, вместо того, чтобы заставлять приложение управлять ею. Если выполняющаяся программа (процесс) использует, а затем освобождает память, эта освободившаяся память остается выделенной процессу. За кадром система Linux управляет блоками памяти, которые программист использует как набор физических "страниц" в памяти, размером 4 Кбайт каждая. Но если страница памяти в данный момент не используется, диспетчер управления памятью ОС Linux сможет переместить ее из оперативной памяти в область свопинга (это называется обменом страниц), где она слабо влияет на потребление ресурсов. Если программа пытается обратиться к данным на странице, которая была перенесена в область свопинга, Linux на очень короткое время приостанавливает программу, возвращает страницу обратно из области свопинга в физическую память и затем разрешает программе продолжить выполнение так, будто данные все время находились в оперативной памяти.

#include <stdlib.h>

void free(void *ptr_to_memory);

Вызов

free
следует выполнять только с указателем на память, выделенную с помощью вызова
malloc
,
calloc
или
realloc
. Очень скоро вы встретитесь с функциями
calloc
и
realloc
. А сейчас выполните упражнение 7.6.

Упражнение 7.6. Освобождение памяти

Эта программа называется memory6.c.

#include <stdlib.h>

#include <stdio.h>

#define ONE_K (1024)

int main {

 char *some_memory;

 int exit code = EXIT_FAILURE;

 some_memory = (char*)malloc(ONE_K);

 if (some_memory != NULL) {

free(some_memory);

printf("Memory allocated and freed again\n");

exit_code = EXIT_SUCCESS;

 }

 exit(exit_code);

}

Вывод программы следующий:

$ ./memory6

Memory allocated and freed again

Как это работает

Эта программа просто показывает, как вызвать функцию

free
с указателем, направленным на предварительно выделенную область памяти.

Примечание

Помните о том,

что после вызова
free
для освобождения блока памяти этот блок больше не принадлежит процессу. Он больше не управляется библиотекой
malloc
. Никогда не пытайтесь читать из области памяти или писать в область памяти, для которой была вызвана функция
free
.

Другие функции распределения памяти

Две другие функции распределения или выделения памяти

calloc
и
realloc
применяются не так часто, как
malloc
и
free
.

Далее приведены их прототипы:

#include <stdlib.h>

void *calloc(size_t number_of_elements, size_t element_size);

void *realloc(void *existing_memozy, size_t new_size);

Несмотря на то, что функция

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

Функция

realloc
изменяет размер предварительно выделенного блока памяти. Она получает в качестве параметра указатель на область памяти, предварительно выделенную функциями
malloc
,
calloc
или
realloc
, и уменьшает или увеличивает эту область в соответствии с запросом. Функция бывает вынуждена для достижения результата в перемещении данных, поэтому важно быть уверенным в том, что к памяти, выделенной после вызова
realloc
, вы всегда обращаетесь с помощью нового указателя и никогда не используете указатель, установленный ранее до вызова функции
realloc
.

Другая проблема, за которой нужно следить, заключается в том, что функция

realloc
возвращает пустой указатель при невозможности изменить размер блока памяти. Это означает, что в приложениях следует избегать кода, подобного приведенному далее:

my_ptr = malloc(BLOCK_SIZE);

...

my_ptr = realloc(my_ptr, BLOCK_SIZE * 10);

Если

realloc
завершится аварийно, она вернет пустой указатель; переменная
my_ptr
будет указывать в никуда и к первоначальной области памяти, выделенной функцией
malloc
, больше нельзя будет обратиться с помощью указателя
my_ptr
. Следовательно, было бы полезно сначала запросить новый блок памяти с помощью
malloc
, а затем скопировать данные из старого блока памяти в новый блок с помощью функции
memcpy
и освободить старый блок памяти вызовом
free
. При возникновении ошибки это позволит приложению сохранить доступ к данным, хранящимся в первоначальном блоке памяти, возможно, на время организации корректного завершения программы.

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

На Берлин!

Дорничев Дмитрий
2. Моё пространственное убежище
Фантастика:
фэнтези
боевая фантастика
рпг
постапокалипсис
5.56
рейтинг книги
На Берлин!

Мастер 7

Чащин Валерий
7. Мастер
Фантастика:
фэнтези
боевая фантастика
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Мастер 7

Последний Герой. Том 2

Дамиров Рафаэль
2. Последний герой
Фантастика:
попаданцы
альтернативная история
4.50
рейтинг книги
Последний Герой. Том 2

Локки 7. Потомок бога

Решетов Евгений Валерьевич
7. Локки
Фантастика:
аниме
эпическая фантастика
фэнтези
5.00
рейтинг книги
Локки 7. Потомок бога

Изгой Проклятого Клана. Том 6

Пламенев Владимир
6. Изгой
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Изгой Проклятого Клана. Том 6

Московское золото и нежная попа комсомолки. Часть Третья

Хренов Алексей
3. Летчик Леха
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Московское золото и нежная попа комсомолки. Часть Третья

Вперед в прошлое 5

Ратманов Денис
5. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 5

Креститель

Прозоров Александр Дмитриевич
6. Ведун
Фантастика:
фэнтези
8.60
рейтинг книги
Креститель

Призыватель нулевого ранга

Дубов Дмитрий
1. Эпоха Гардара
Фантастика:
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Призыватель нулевого ранга

Дитя прибоя

Трофимов Ерофей
Дитя прибоя
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Дитя прибоя

Инженер Петра Великого 2

Гросов Виктор
2. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Инженер Петра Великого 2

Камень. Книга 4

Минин Станислав
4. Камень
Фантастика:
боевая фантастика
7.77
рейтинг книги
Камень. Книга 4

Я все еще не царь. Книга XXVI

Дрейк Сириус
26. Дорогой барон!
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Я все еще не царь. Книга XXVI

Кровь на эполетах

Дроздов Анатолий Федорович
3. Штуцер и тесак
Фантастика:
альтернативная история
7.60
рейтинг книги
Кровь на эполетах