Модель памяти в языке Си

Модель памяти в языке Си — система хранения объектов в языке Си[1].

Способ хранения объекта в языке Си определяет его время жизни — часть времени выполнения программы, во время которого объект существует или для него зарезервировано место. Объект имеет постоянный адрес и сохраняет своё последнее значение. Запрещается обращаться к объекту, который перестал существовать, при этом, если при работе с объектом использовался указатель, его значение остаётся неопределённым.

Существует три способа хранения объектов[1]: автоматический, статический и динамический.

СвойствоАвтоматическийСтатическийДинамический
ОбъявлениеОбъект без связывания и без staticИмеет внутреннее или внешнее связывание или объявлен с квалификатором staticВыделен с помощью malloc
Время существованияБлок, в котором объявлен объектВсё время выполнения программыОт вызова malloc до вызова free
ИнициализацияОтсутствует в случае отсутствия явной инициализацииПроисходит один раз до запуска программыЧастично в случае calloc
РазмерФиксированный, неизменяемыйФиксированный, неизменяемыйЛюбой, изменяемый
Типичное размещениеСтек или регистры процессораОтдельный сегмент памятиКуча

Статический объект можно инициализировать явно, либо использовать умалчиваемую инициализацию.

При использовании функции calloc все объекты имеют нулевое значение кроме чисел с плавающей запятой и указателей[2].

Выражения, не являющиеся lvalue, связанные с обращением к массиву, являющегося членом структуры (struct) или объединения (union) имеют время существования, ограниченное оценкой такого выражения[1].

Си-строки, которыми инициализируются указатели char*, имеют статический тип хранения и не должны изменяться[3].

Динамическая память

Ни один объект не может находиться в динамической памяти без явного указания программиста. Для работы с динамической памятью существуют функции malloc, calloc, realloc и free. Поскольку функции, выделяющие память, принимают размер в переменной типа size_t, максимальный объём выделяемой памяти ограничен SIZE_T_MAX[1].

Функции malloc и calloc выделяют память, которая после использования должна быть освобождена с помощью вызова free. После освобождения значение указателя остаётся неопределённым. Функция realloc возвращает указатель на изменённый блок памяти, если запрос не может быть удовлетворён, размер блока памяти не изменяется[1].

#include <stdlib.h>

void foo (void **ptr, size_t size)
{
   *ptr = realloc (*ptr, size+128); /* утечка памяти, если realloc вернёт NULL */
   if (!*ptr)
   {
     ...
   }
}

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

Пример

#include <stdlib.h>
#include <string.h>

static int x; /* 0 по умолчанию, существует всё время выполнения */
static int y=45; /* 45, существует всё время выполнения */

int cnt(void)
{
    static int i=0;/*статический тип, инициализируется нулём только при запуске 
        программы, а не каждый вызов функции */
    int j=-1;/*автоматический тип, инициализируется каждый раз 
                при вызове функции -1*/    
    i++;/* увеличивается на 1 в статической области памяти каждый запуск функции*/
    j++;/* увеличивается на 1 локальная переменная */
    return (i+j);/*при первом вызове с запуска программы функция вернёт 1, 
        при втором вызове 2, ... */
}

int main (void)
{
	char arr[50] = "This is object of automatic storage duration";
	/* имеет автоматический тип,существует до выхода из main,
	начальные 45 элементов массива инициализированы элементами 
	строки с закрывающим нулём, остальные не определены */
    char *line = "Simple line"; /*автоматический тип, существует до выхода 
    из main, line инициализирован указателем на константу */
    
	int y; /* значение не определено, существует до выхода из main*/
	int z=10; /* значение определено, существует до выхода из main*/
	char *ptr; /* значение указателя не определено */
	ptr = malloc (50); /* значение по указателю не определено, 
	                объект по указателю существует до вызова free */
	strcpy (ptr, arr);
	free (ptr);
	return 0;
}

Примечания

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.