Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

9899 - Полный справочник по языку Си - Выпуск 2: Модель памяти


Информационный Канал Subscribe.Ru


"9899"
Полный справочник по языку Си
Выпуск 2: Модель памяти
Наряду со способами представления данных и семантикой исполнения программ модель памяти ― одна из основных составляющих любой абстрактной машины. Так, практически каждая программа вынуждена делать те или иные предположения об устройстве памяти, и только хорошее владение этой темой может дать надежду на получение достаточно переносимого, безопасного и эффективного кода.
Байт в Си и Си++
С точки зрения Си и Си++ байт ― это наименьшая адресуемая ячейка памяти, составленная из 8-ми или более разрядов, каждый из которых является значащим (value bit), т. е. участвует в образовании значения. Кроме того гарантировано, что байта достаточно для размещения любого символа из основного набора символов среды исполнения (basic execution character set).
Как правило, байт в терминах целевой платформы (т. е. то, что принято называть байтом на этой платформе) ― это тот байт, который производитель инструментария выбирает для реализации абстрактной машины, однако удобный выбор не всегда однозначен. Так, [C99 Rationale] приводит в пример машину с 36-разрядным словом (адресуемой ячейкой), для которой байт может быть выбран 9-, 12-, 18- или 36-разрядным, поскольку все эти числа не меньше 8-ми и делят 36 нацело ([C99 Rationale 3]).
Последовательности байтов
Вся память, доступная программам на Си и Си++ образуется множеством непрерывных последовательностей байтов (byte sequences), каждый из которых имеет уникальный адрес.
Последовательности выделяются и освобождаются в процессе выполнения программ либо автоматически средой исполнения, либо динамически с помощью функций и операций (в Си++) управления памятью. При этом важно, что любой объект ― это, по определению, некоторая область памяти размером в целое число байтов, а значит размещение любых объектов в таких последовательностях всегда возможно ([1]). Допустимо, и это вполне вероятно, что вновь выделенная последовательность байтов будет пересекаться по адресам с одной из ранее освобожденных последовательностей.
Несмотря на то, что для большинства реализаций имеется, а иногда даже задокументирована связь между порядком объявлений объектов и взаимным расположением в памяти соответствующих им последовательностей байтов, стандартами это взаимное расположение никак не определено. Кроме того, использование операций < (меньше), > (больше), <= (меньше или равно) и >= (больше или равно) для сравнения адресов, принадлежащих разным последовательностям, являются случаями неопределенного поведения (undefined behavior), хотя и это вполне корректно для многих реализаций.
В языке Си++, в силу практики применения стандартных контейнеров, такие функциональные объекты сравнения (comparison function objects) как greater, less, greater_equal и less_equal, специализированные для указательных типов, наделены способностью упорядочивать даже адреса, принадлежащие разным последовательностям.
На равенство (операция ==) и неравенство (операция !=) и в Си, и в Си++ можно сравнивать адреса, принадлежащие любым последовательностям байтов.
Пример:

#include <stdlib.h> int main(void) { /* размещаются средой исполнения */ int r, i, j, a[10], *p, *q; r = (&i == &j); /* r равно 0 */ r = (&i > &j); /* r не определено */ p = a + 5; q = a + 7; r = (p > q); /* r равно 0 */ /* выделяются динамически */ p = malloc(sizeof(int)); q = malloc(sizeof(int[5])); if(p != NULL && q != NULL) { r = (p != q); /* r равно 1 */ r = (p < q || p > q); /* r не определено */ } /* освобождаются динамически */ free(q); free(p); /* r, i, j, a, p и q освобождаются автоматически */ return EXIT_SUCCESS; }

Размещение регистровых объектов
В языке Си адреса объектов класса памяти register (register storage class) не могут быть получены даже неявно, поэтому они всегда используются вне каких бы то ни было предположений относительно устройства модели памяти. Адресованные регистровые объекты в Си++ можно рассматривать как любые другие объекты автоматической продолжительности хранения (automatic storage duration).
Размещение функций
Похожим образом, размещение функций, хотя указатели на них и могут быть получены, никак не учитывается моделью памяти, т. е. функции считаются расположенными в самостоятельном адресном пространстве. Как следствие, любые преобразования и сравнения между указателями на функции и объекты являются случаями неопределенного поведения.
Память только для чтения
Любая последовательность байтов, которая заведомо не будет модифицирована, может быть размещена в памяти только для чтения (read-only memory). Кроме того, размещение некоторых объектов допускается в памяти только для чтения даже тогда, когда они имеют не const-квалифицированный тип. В качестве примеров таких объектов можно привести аргументы командной строки, передаваемые в функцию main и результаты функций getenv и strstr, когда последняя производит поиск в строке, размещенной в памяти только для чтения.
volatile-объекты
В отличие от всех прочих, модификация значений volatile-квалифицированных объектов допустима и помимо хода выполнения программы. Учитывая это, реализация не делает никаких предположений относительно значений таких объектов и каждое обращение к ним (access) действительно производится.
Совместимость моделей памяти Си и Си++
Модель памяти Си++ в объеме требований языка Си полностью совместима с моделью памяти Си. Имеет смысл различать эти модели только в свете дополнительных определений языка Си++.

[1] При динамическом выделении последовательности нулевого размера только от конкретной реализации зависит, вернет ли стандартная функция выделения памяти NULL или некоторый уникальный адрес. Подобные рассуждения об автоматическом размещении объектов бессмысленны, поскольку автоматический объект нулевого размера не может быть образован.
    В следующем выпуске
Тема третьего выпуска ― представление данных. Речь пойдет о том, каким образом представление значений объектов укладывается в модель памяти и особенности аппаратных платформ.
Мы по-прежнему ждем Ваших откликов. Пишите нам.
С лучшими пожеланиями,
редакция рассылки "9899"
    Ссылки
Модель памяти (memory model): [C99 Rationale 3], [C++ 1.7, 3.9]; байт (byte): [C99 3.6, 5.2.4.2.1, 6.5.3.4, J.3.4]; значащие разряды (value bits): [C99 6.2.6.2], [C99 Rationale 3]; значение (value): [C99 3.17, 5.2.4.2.1, 6.2.5, 6.2.6], [C99 Rationale 3, 6.5.3.4], [C++ 1.7]; объект (object): [C99 3.14, 5.2.4.1, 6.2.4, 6.2.5, 6.2.6], [C99 Rationale 3, 6.3.2.3], [C++ 1.8]; основной набор символов среды исполнения (basic execution character set): [C99 5.1.1.2, 5.2.1, 6.2.5], [C99 Rationale 5.2.1], [C++ 2.1, 2.2]; последовательность байтов (byte sequence): [C99 Rationale 3, 7.21.1], [C++ 1.7]; функции управления памятью (memory management functions, dynamic memory management): [C99 7.20.3], [C99 Rationale 7.20.3], [C++ 18.4, 20.4.6]; адрес (address): [C99 3.5, 3.6, 6.2.4], [C++ 1.7]; операции проверки отношения (relational operators): [C99 6.5.8, F.8.3, J.2], [C99 Rationale 6.5.8], [C++ 5.9]; неопределенное поведение (undefined behavior): [C99 3.4.3], [C99 Rationale 3], [C++ 1.3.12]; функциональные объекты сравнения (comparison function objects): [C++ 20.3.3]; операции проверки равенства (equality operators): [C99 6.5.9], [C99 Rationale 6.5.9], [C++ 5.10]; макрос NULL (NULL macro): [C99 7.17 #3, J.3.12], [C99 Rationale 6.5.9, 7.17], [C++ 18.1 #4]; спецификатор класса памяти register (register storage class specifier): [C99 6.7.1], [C99 Rationale 6.7.1]; адресное пространство (address space): [C99 Rationale 6.7.1]; продолжительность хранения (storage duration): [C99 6.2.4], [C99 Rationale 6.2.4], [C++ 1.8, 3.7]; память только для чтения (read-only memory): [C99 6.7.3], [C99 Rationale 6.4.5, 6.7.3]; квалификаторы типов (type qualifiers): [C99 6.7.3], [C99 Rationale 6.7.3], [C++ 3.9.3]; обращение (access): [C99 3.1, 5.1.2.3, 6.7.3].
    Список литературы
[C99] ISO/IEC 9899:1999, Programming Languages ― C
[C99 Rationale] ISO/IEC N897, Rationale for Inetrnational Standard ― Programming Languages ― C
[C++] ISO/IEC 14882:1998, Programming Languages ― C++
© Иван Косарев, 2004. Все права защищены. Публикация и цитирование разрешены только с письменного согласия автора.

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное