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

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

Жанры

Основы программирования в 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);

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

Николай Гоголь

Труайя Анри
Проза:
историческая проза
6.40
рейтинг книги
Николай Гоголь

Народ, да!

Коллектив авторов
Старинная литература:
мифы. легенды. эпос
5.00
рейтинг книги
Народ, да!

История человечества. Россия

Харченко Павел
Научно-образовательная:
история
5.00
рейтинг книги
История человечества. Россия

Последний Паладин. Том 14

Саваровский Роман
14. Путь Паладина
Фантастика:
аниме
фэнтези
попаданцы
5.75
рейтинг книги
Последний Паладин. Том 14

"Фантастика 2024-164". Компиляция. Книги 1-25

Злотников Роман Валерьевич
Фантастика 2024. Компиляция
Фантастика:
боевая фантастика
попаданцы
альтернативная история
аниме
фэнтези
5.00
рейтинг книги
Фантастика 2024-164. Компиляция. Книги 1-25

Киберпространство

Ливадный Андрей Львович
43. Экспансия: История Галактики
Фантастика:
космическая фантастика
7.69
рейтинг книги
Киберпространство

QT 4: программирование GUI на С++

Саммерфилд Марк
Компьютеры и Интернет:
программирование
5.00
рейтинг книги
QT 4: программирование GUI на С++

Игра реальностей. Дрейк

Мелан Вероника
1. Город. Игра реальностей
Любовные романы:
любовно-фантастические романы
5.75
рейтинг книги
Игра реальностей. Дрейк

Хроники Сиалы. Трилогия

Пехов Алексей Юрьевич
Хроники Сиалы
Фантастика:
фэнтези
9.03
рейтинг книги
Хроники Сиалы. Трилогия

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
7.33
рейтинг книги
Тринадцатый

Новая трилогия Возвышения. Том 1

Брин Дэвид
Шедевры фантастики
Фантастика:
научная фантастика
7.00
рейтинг книги
Новая трилогия Возвышения. Том 1

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

Винокуров Юрий
19. Кодекс Охотника
Фантастика:
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XIX

Танец отражений

Буджолд Лоис Макмастер
9. Сага о Форкосиганах
Фантастика:
научная фантастика
9.12
рейтинг книги
Танец отражений

Замок (сборник)

Вилсон Фрэнсис Пол
Мастера остросюжетного романа
Фантастика:
мистика
5.00
рейтинг книги
Замок (сборник)