WikiSort.ru - Программирование

ПОИСК ПО САЙТУ | о проекте

Модель памяти в языке Си — система хранения объектов в языке Си[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].

 1 #include <stdlib.h>
 2 
 3 void foo (void **ptr, size_t size)
 4 {
 5    *ptr = realloc (*ptr, size+128); /* утечка памяти, если realloc вернёт NULL */
 6    if (!*ptr)
 7    {
 8      ...
 9    }
10 }

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

Пример

#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;
}

Примечания

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

Другой контент может иметь иную лицензию. Перед использованием материалов сайта WikiSort.ru внимательно изучите правила лицензирования конкретных элементов наполнения сайта.

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии