Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Размещение объектов переменной длины с использованием одного стека

Упомянутый выше фрагмент программы можно переписать так:

размер = Вычислить размер для БД (список поставщиков);
Таблица БД* поставщики = Выделить память в своём стеке (размер);
Конструктор таблицы БД (поставщики, список поставщиков);

размер = Вычислить размер для БД (список покупателей);
Таблица БД* покупатели = Выделить память в своём стеке (размер);
Конструктор таблицы БД (покупатели, список покупателей);

размер = Вычислить размер для БД (поставщики, покупатели);
Таблица БД* контрагенты = Выделить память в своём стеке (размер);
Объединить (контрагенты, поставщики, покупатели);
            Выполнять сдвиг указателя на вершину стека можно не только для чужого стека, но и для собственного. Достаточно знать размер:
SUB  ESP, <object size>
            В случае одностековой модели необходимо, в первую очередь, вычислить размер объекта, опираясь на некоторые входные данные. Затем необходимое количество памяти резервируется в своём собственном стеке. Далее конструктору передаётся в дополнение к списку параметров ещё и адрес для размещения объекта.

            Такой вариант оправдан тогда, когда требуемый размер памяти легко вычисляется. Но возможен случай, когда для вычисления размера требуются достаточно объемные вычисления, которые во многом совпадают с теми вычислениями, которые производит конструктор. Чтобы избежать удвоения вычислений, вычислять объём памяти можно прямо в конструкторе, используя два стека.

            Перед выходом из тех функций, чей стек сдвигался (для обоих моделей — двухстековой и одностековой), необходимо восстановить адрес вершины стека в исходное положение. Соответственно, в начале функции необходимо сохранить значение ESP в локальной переменной, а перед выходом восстановить:
int  копия ESP; {__asm   mov  копия ESP, ESP}
{__asm   mov  ESP, копия ESP}
            Нужно помнить, что двухстековая модель не нужна в том случае, если возвращаемые из функции объекты имеют заранее известный размер. Это могут быть как атомарные объекты, так и контейнеры известного размера. Использовать один стек в этом случае не только можно, но и должно, такой вызов функций немного быстрее.

            Выбор «или-или» между одно- или двухстековой моделью не стоит. Обе отлично уживаются друг с другом. Вызов же традиционных функций, возвращающих объект фиксированной длины, остаётся таким же, как и раньше. Это один из принципов C++, который гласит: «Вы не платите за то, что не используете». В случае, когда функции возвращают объект переменной длины, вся расплата заключается в использовании считанного количества процессорных команд. Сравните это с кодом из сотен строк на C функции malloc().

Как обойтись без двухстековой модели

  • Сделать все конструкторы объектов неизвестного на этапе компиляции размера inline-функциями. Поскольку при подстановке не происходит вызова программы, то нет необходимости заботиться о том, чтобы не затереть входные параметры, адрес возврата, локальные объекты. В этом случае память выделяется с помощью alloca().

                Этот подход имеет ограничение. Подставляемая inline-функция не имеет адреса, поэтому её нельзя использовать как объект первого класса: передать её адрес в функцию или возвратить его из функции.
  • Конструировать объекты в два этапа
    1. узнать размер создаваемого объекта и выделить участок памяти этого размера с помощью alloca(),
    2. создать объект (конструктор).


                Этот подход тоже имеет ограничение. Адрес конструктора можно использовать как объект первого класса. Но этого не достаточно, ведь перед вызовом конструктора нужно сперва вызвать функцию, вычисляющую размер. Для обеспечения корректности работы требуется передавать в таком случае не один адрес, а два: вычислителя размера и собственно конструктор.

                Этот подход так же вступает в противоречие с ООП, которое подразумевает, что работа с объектом начинается с создания объекта, т.е. конструктора. Но как и куда втиснуть определитель размера, который должен отработать до конструктора, передав ему требуемый размер? Всё было гладко, когда размеры имели фиксированный, заранее известный размер. Языки типа PHP или SmallTalk не в счёт: там фиксированный размер имеют указатели (или толстые указатели) на участок динамической памяти, куда размещается собственно объект.
            Конструируя новый язык, можно смягчить влияние этих ограничений: ведь перед нами чистый лист, и что там будет написано, зависит от нас. Тем не менее, ограничения будут иметь место при внесении в язык черт функционального программирования. Для ФП вообще характерен упор на функции, и там придётся столкнуть с необходимостью единого конструктора, внутри которого происходит вычисление размера создаваемого объекта.

            Читаем далее следующую статью: Можно ли забыть о «куче», если объекты переменной длины хранить в стеке.

Почитайте ещё:

Опубликовано: 2014.07.27, последняя правка: 2018.10.29    16:02

ОценитеОценки посетителей
   ▌ 0
   ██████████████████████████████████████████ 1 (100%)
   ▌ 0
   ▌ 0

Добавить свой отзыв

Написать автору можно на электронную почту
mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

●  Устарел ли текст как форма представления программы

●  Русский язык и программирование

●  Многоязыковое программирование

Синтаксис языков программирования

Синтаксический сахар

●  Некоторые «вкусности» Алгол-68

●  «Двухмерный» синтаксис Python

●  Почему языки с синтаксисом Си популярнее языков с синтаксисом Паскаля?

●  Должна ли программа быть удобочитаемой?

●  Стиль языка программирования

●  Тексто-графическое представление программы

●●  Разделители

●●  Строки программы

●●  Слева направо или справа налево?

●  Комментарии

●●  Длинные комментарии

●●  Короткие комментарии

●●  Комментарии автоматической генерации документации

●●  Нерабочий код

●●  Помеченные комментарии

●  Нужны ли беззнаковые целые?

●  Шестнадцатиричные и двоичные константы

●  Условные операторы

●  Переключатель

●  Циклы

●●  Продолжение цикла и выход из него

●  Некошерный «goto»

●  Изменение приоритетов операций

●  Операции присвоения и проверки на равенство. Возможно ли одинаковое обозначение?

●  Так ли нужны операции «&&», «||» и «^^»?

●  Постфиксные инкремент и декремент

●  Почему в PHP для конкатенации строк используется «.»?

●  Указатели и ссылки в C++

●●  О неправомерном доступе к памяти через указатели

●  Обработка ошибок

●  Функциональное программирование

●●  Нечистые действия в чистых функциях

●●  О чистоте и нечистоте функций и языков

●●  Макросы — это чистые функции, исполняемые во время компиляции

●●  Хаскелл, детище британских учёных

●●  Измеряем замедление при вызове функций высших порядков

●●  C vs Haskell: сравнение скорости на простом примере

●●  Уникальность имён функций: за и против

●●  Каррирование: для чего и как

●●  О тестах, доказывающих отсутствие ошибок

●  Надёжные программы из ненадёжных компонентов

●●  О многократном резервировании функций

●  Использование памяти

●  Почему динамическое распределение памяти — это плохо

●  Как обеспечить возврат функциями объектов переменной длины?

●●  Типы переменного размера (dynamically sized types, DST) в языке Rust

●●  Массивы переменной длины в C/C++

●●  Размещение объектов в стеке, традиционный подход

●●  Размещение объектов переменной длины с использованием множества стеков

●●  Размещение объектов переменной длины с использованием двух стеков

●●  Реализация двухстековой модели размещения данных

●●  Двухстековая модель: тесты на скорость

●●  Изменение длины объекта в стеке во время исполнения

●●  Размещение объектов переменной длины с использованием одного стека

●  Можно ли забыть о «куче», если объекты переменной длины хранить в стеке

●  Безопасность и размещение объектов переменной длины в стеке

●  Массивы, структуры, типы, классы переменной длины

●  О хранении данных в стеке, вместо заключения

●  Реализация параметрического полиморфизма

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Новости и прочее




Последние отзывы

2024/04/18 11:14 ••• Ivan
Энтузиасты-разработчики компиляторов и их проекты

2024/04/18 04:47 ••• void
Признаки устаревшего языка

2024/04/11 00:08 ••• Автор сайта
Постфиксные инкремент и декремент

2024/04/09 23:50 ••• Автор сайта
Русский язык и программирование

2024/04/07 15:33 ••• MihalNik
Все языки эквивалентны. Но некоторые из них эквивалентнее других

2024/04/01 23:39 ••• Бурановский дедушка
Новости и прочее

2024/04/01 23:32 ••• Бурановский дедушка
Русской операционной системой должна стать ReactOS

2024/03/22 20:41 ••• void
Раскрутка компилятора

2024/03/20 19:54 ••• kt
О многократном резервировании функций

2024/03/20 13:13 ••• Неслучайный читатель
Надёжные программы из ненадёжных компонентов

2024/03/07 14:16 ••• Неслучайный читатель
«Двухмерный» синтаксис Python

2024/03/03 16:49 ••• Автор сайта
О неправомерном доступе к памяти через указатели

2024/02/28 18:59 ••• Вежливый Лис
Про лебедей, раков и щук