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

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

Жанры

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

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

Примечание

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

malloc
. Называется оно уничтожением из-за нехватки памяти (out of memory (OOM) killer), и хотя может показаться чересчур радикальным,
на самом деле служит разумным компромиссом между возможностью быстрого и эффективного выделения памяти процессам и необходимостью собственной защиты ядра от полного исчерпания ресурсов, что является серьезной проблемой.

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

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

malloc
, нет смысла? Конечно же нет. Одна из самых распространенных проблем в программах на языке С, использующих динамическую память, — запись за пределами выделенного блока. Когда это происходит, программа может не завершиться немедленно, но вы, вероятно, перезапишите некоторые внутренние данные, используемые подпрограммами библиотеки malloc.

Обычный результат — аварийное завершение последующих вызовов

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

Неправильное обращение к памяти

Предположим, что вы хотите сделать что-то "плохое" с памятью. В упражнении 7.4 в программе memory4.c вы выделяете некоторую область памяти, а затем пытаетесь записать данные за пределами выделенной области.

Упражнение 7.4. Неправильное обращение к вашей памяти

#include <stdlib.h>

#define ONE_K (1024)

int main {

 char *some_memory;

 char *scan_ptr;

 some_memory = (char *)malloc(ONE_K);

 if (some_memory == NULL) exit(EXIT_FAILURE);

 scan_ptr = some_memory;

 while (1) {

*scan_ptr = '\0';

scan_ptr++;

 }

 exit(EXIT_SUCCESS);

}

Вывод прост:

$ ./memory4

Segmentation fault

Как

это работает

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

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

Указатель null

Современные системы Linux, в отличие от ОС MS-DOS, но подобно новейшим вариантам ОС Windows, надежно защищены от записи или чтения по адресу, на который ссылается пустой указатель (

null
), хотя реальное поведение системы зависит от конкретной реализации.

Выполните упражнение 7.5.

Упражнение 7.5. Обращение по указателю
null

Давайте выясним, что произойдет, когда мы попытаемся обратиться к памяти по пустому или null-указателю в программе memory5a.c.

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

int main {

 char *some_memory = (char*)0;

 printf("A read from null %s\n", some_memory);

 sprintf(some_memory, "A write to null\n");

 exit(EXIT_SUCCESS);

}

Будет получен следующий вывод:

$ ./memory5a

A read from null (null)

Segmentation fault

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

Первая функция

printf
пытается вывести строку, полученную от указателя
null
; далее
sprintf
пытается записать по указателю
null
. В данном случае Linux (под видом библиотеки GNU С) простила чтение и просто предоставила "магическую" строку, содержащую символы
(null)\0
. Система не столь терпима в случае записи и просто завершила программу. Такое поведение порой полезно при выявлении программных ошибок.

Если вы повторите попытку, но не будете использовать библиотеку GNU С, вы обнаружите, что безадресное чтение не разрешено. Далее приведена программа memory5b.c:

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

int main {

 char z = *(const char *)0;

 printf("I read from location zero\n");

 exit(EXIT_SUCCESS);

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

Все, что шевелится

Федотов Сергей
Фантастика:
юмористическая фантастика
5.00
рейтинг книги
Все, что шевелится

Виконт. Книга 3. Знамена Легиона

Юллем Евгений
3. Псевдоним `Испанец`
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Виконт. Книга 3. Знамена Легиона

Серпентарий

Мадир Ирена
Young Adult. Темный мир Шарана. Вселенная Ирены Мадир
Фантастика:
фэнтези
готический роман
5.00
рейтинг книги
Серпентарий

Потомок бога 3

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

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

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

Адепт. Том 1. Обучение

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
9.27
рейтинг книги
Адепт. Том 1. Обучение

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

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

Страж Кодекса. Книга IV

Романов Илья Николаевич
4. КО: Страж Кодекса
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Страж Кодекса. Книга IV

Возмутитель спокойствия

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

Цикл "Отмороженный". Компиляция. Книги 1-14

Гарцевич Евгений Александрович
Отмороженный
Фантастика:
боевая фантастика
рпг
постапокалипсис
5.00
рейтинг книги
Цикл Отмороженный. Компиляция. Книги 1-14

Сирийский рубеж 2

Дорин Михаил
6. Рубеж
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сирийский рубеж 2

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Я не князь. Книга XIII

Дрейк Сириус
13. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я не князь. Книга XIII

Шайтан Иван 4

Тен Эдуард
4. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
8.00
рейтинг книги
Шайтан Иван 4