Нейл Мэтью - Основы программирования в Linux
- Название:Основы программирования в Linux
- Автор:
- Жанр:
- Издательство:«БХВ-Петербург»
- Год:2009
- Город:Санкт-Петербург
- ISBN:978-5-9775-0289-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Нейл Мэтью - Основы программирования в Linux краткое содержание
В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стандартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым.
Для начинающих Linux-программистов
Основы программирования в Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Означает ли этот, по-видимому, неограниченный источник памяти с последующим прерыванием и уничтожением процесса, что в проверке результата, возвращаемого функцией malloc
, нет смысла? Конечно же нет. Одна из самых распространенных проблем в программах на языке С, использующих динамическую память, — запись за пределами выделенного блока. Когда это происходит, программа может не завершиться немедленно, но вы, вероятно, перезапишите некоторые внутренние данные, используемые подпрограммами библиотеки malloc.
Обычный результат — аварийное завершение последующих вызовов malloc
не из- за нехватки памяти, а из-за повреждения структур памяти. Такие проблемы бывает трудно отследить, и чем быстрее в программах обнаружится ошибка, тем больше шансов найти причину. В главе 10, посвященной отладке и оптимизации, мы обсудим некоторые средства, которые могут помочь вам выявить проблемы, связанные с памятью.
Неправильное обращение к памяти
Предположим, что вы хотите сделать что-то "плохое" с памятью. В упражнении 7.4 в программе memory4.c вы выделяете некоторую область памяти, а затем пытаетесь записать данные за пределами выделенной области.
#include
#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.
null
Давайте выясним, что произойдет, когда мы попытаемся обратиться к памяти по пустому или null-указателю в программе memory5a.c.
#include
#include
#include
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
#include
#include
int main() {
char z = *(const char *)0;
printf("I read from location zero\n");
exit(EXIT_SUCCESS);
}
Вы получите следующий результат:
$ ./memory5b
Segmentation fault
В этот раз вы пытаетесь прочесть непосредственно из нулевого адреса. Между вами и ядром теперь нет GNU-библиотеки libc, и программа прекращает выполнение. Имейте в виду, что некоторые системы UNIX разрешают читать из нулевого адреса, ОС Linux этого не допускает.
Освобождение памяти
До сих пор мы выделяли память и затем надеялись на то, что по завершении программы использованная нами память не будет потеряна, К счастью, система управления памятью в ОС Linux вполне способна с высокой степенью надежности гарантировать возврат памяти в систему по завершении программы. Но большинство программ просто не хотят распределять память, используют ее очень короткий промежуток времени и затем завершаются. Гораздо более распространено динамическое использование памяти по мере необходимости.
Программы, применяющие память на динамической основе, должны всегда возвращать неиспользованную память диспетчеру распределения памяти malloc
с помощью вызова free
. Это позволяет выделить блоки, нуждающиеся в повторном объединении, и дает возможность библиотеке malloc
следить за памятью, вместо того, чтобы заставлять приложение управлять ею. Если выполняющаяся программа (процесс) использует, а затем освобождает память, эта освободившаяся память остается выделенной процессу. За кадром система Linux управляет блоками памяти, которые программист использует как набор физических "страниц" в памяти, размером 4 Кбайт каждая. Но если страница памяти в данный момент не используется, диспетчер управления памятью ОС Linux сможет переместить ее из оперативной памяти в область свопинга (это называется обменом страниц), где она слабо влияет на потребление ресурсов. Если программа пытается обратиться к данным на странице, которая была перенесена в область свопинга, Linux на очень короткое время приостанавливает программу, возвращает страницу обратно из области свопинга в физическую память и затем разрешает программе продолжить выполнение так, будто данные все время находились в оперативной памяти.
#include
void free(void *ptr_to_memory);
Вызов free
следует выполнять только с указателем на память, выделенную с помощью вызова malloc
, calloc
или realloc
. Очень скоро вы встретитесь с функциями calloc
и realloc
. А сейчас выполните упражнение 7.6.
Эта программа называется memory6.c.
#include
#include
#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);
Интервал:
Закладка: