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

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

  • Потеря эффективности. Простейшие реализации функций malloc() и free() имеют длину несколько сотен строк. А уж продвинутые — тем паче длиннее.

  • Некорректная работа с памятью в куче может приводить к её утечкам. Причиной может быть как ошибки в библиотечных функциях управления памятью, так и ошибки в программе при ручном управлении.
  • Фрагментация памяти. Если «до упора» выделять память по одному байту, а потом освободить занятые блоки памяти, но не все, а через один, то память будет нарезана на множество маленьких кусочков, которые невозможно использовать. Сложные алгоритмы распределения памяти могут обходить эту проблему путём перемещения фрагментов и изменения указателей. Но это опять расходование вычислительных ресурсов.
  • Алгоритмы динамического распределения памяти либо просты, либо хороши. Более того, одни алгоритмы хорошо работают для одного класса задач, а другие — для другого.
  • Некоторые алгоритмы динамического распределения памяти выделяют память быстро, но в ситуациях, когда память заканчивается и нужно обеспечить «сборку мусора», начинают «тормозить». Имея хорошее среднее время отклика, они не могут обеспечить его гарантированный минимум. Поэтому в системах реального времени используют другие алгоритмы. Они имеют гарантированное время отклика, но среднее время отклика у них выше.
  • Ссылки на участки памяти в «куче» могут быть потеряны. В этом случае память не может быть освобождена, поскольку её адрес становится неизвестен программе. Для решения проблемы используют «умные указатели», которые хоть и решают задачу, но опять же, ценой дальнейшей потери эффективности.
         Есть хорошая статья на эту тему: «4 вида утечек памяти в JavaScript и как с ними бороться»

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

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

Последняя правка: 2018-10-29    16:01

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

Отзывы

     2014/08/05 19:01, Илья

Escape analysis: Java 7 автоматически выделяет объекты не в куче, а на стеке, если это возможно.

     2014/08/15 10:38, Автор сайта

Есть сомнения, что объекты в Java создаются в стеке всегда, когда возможно. В C++ можно создать в стеке массив, размеры которого становятся известны в момент выполнения. Но это возможно лишь с помощью ассемблерных вставок (как это делается — описано в следующих статьях). Но средствами только C++ это невозможно, даже если у Вас отличный оптимизирующий компилятор. Т.е. даже в C++, чей конёк, чья визитная карточка — это скорость выполнения программы, не могут этого сделать, хотя такая возможность очевидна и напрашивается. А ведь один из главных минусов динамического распределения памяти — это потеря скорости.

Вот поэтому есть сомнения насчёт Java. C++ позволяет проверить догадки, предоставляя исполняемый код. Кода Java не видел, поэтому не могу ни подтвердить Ваши слова, ни опровергнуть. Вы можете взять на себя труд: создать массив с размером, известным только во время выполнения, и посмотреть код виртуальной машины?

     2014/09/02 08:54, Илья

К сожалению, я не смогу посмотреть код в этом случае.
Но думается, что большие массивы и не надо создавать на стеке, хотя бы для того, чтобы не нарваться на неожиданный stack overflow, если пользователь задал "немного бо́льшие" параметры.

Автозамена кучи на стек имеет смысл для маленьких объектов:
1) локальность данных
2) сокращение труда сборщика мусора — ему не нужно будет чистить память от мелких временных объектов
3) так как другой поток не может залезть в наш стек, не нужно применять блокирование, даже если оно прописано в программе

     2014/08/15 10:38, Автор сайта

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

     2015/08/02 16:51, Денис Будяк

Использование кучи в общем случае неизбежно из-за того, что не всегда известен порядок уничтожения объектов. Любое наперёд заданное количество стеков (или очередей) не справится с этой проблемой в общем случае. Именно поэтому сборка мусора присутствует в Java, в ядре Линукса и в базе данных Postgress.

Язык, лишённый кучи, будет неполноценным, придётся делать костыли.

     2015/08/03 13:32, Автор сайта

Предлагаемая организация стеков в значительной мере уменьшит обращения к куче, и это хорошо.

Можно ли вообще избавиться от кучи? Интересный вопрос как с точки зрения теории, так и практики. Можно ли алгоритмы с произвольным порядком освобождения памяти преобразовать в эквивалентные, но со строгим порядком? Например, оттягивая фактическое освобождение памяти, помечая её, как освобождённую. Ну и практический вопрос: можно ли выделить какой-то особый класс задач, который нуждается именно в произвольном порядке освобождения памяти?

В чисто функциональных языках программирования предлагаемый метод, мне видется, имеет высокие шансы вообще обходиться без кучи.

     2015/08/04 18:34, Денис Будяк

Не думаю, что можно избавиться, да и неохота об этом думать.

     2015/08/05 13:03, Автор сайта

А вот мне этот вопрос интересен.

     2015/08/09 13:58, Денис Будяк

Пример: линковка программы. В программе на С определена куча функций, одни функции ссылаются на другие. Берём в качестве корня точку входа и от неё делаем сборку мусора по ссылкам функций между собой. Так определяем, какие функции нужны в исполняемом файле.

     2016/04/03 06:05, rst256

Ссылки на участки памяти в «куче» могут быть потеряны.

Ну таким Макаром можно с тем же успехом и в стеке данные про.. хм потерять, или на ноль поделиться, хотя последнее уже кое где закрыли (видать были прецеденты) в некоторых языках 1/0 возвращает или NaN(тупо переносим ошибку подальше от места возникновения) или huge(означает "большое число" — бесконечность, 80% ошибок успешно исправляется, оставшиеся 20% всплывут не скоро).
Как то неправильно ошибки возникшие в прикладном коде вешать на библиотеку.

     2016/04/03 15:24, Автор сайта

Усовершенствование (о котором написано в последующих статьях) заключается вот в чём.
f1(f2(f3(...)))
Функция f3 выделяет память в стеке функции f2 и записывает указатель на неё в стеке f2. Когда f2 заканчивает работу и передаёт управление f1, то перестают существовать как указатель на память в стеке f2, так и сама память в стеке f2 (она освобождается).

     2016/05/05 10:16, utkin

f1(f2(f3(...)))

А зачем такие заморочки? Можно ведь выделять сразу все в стеке f1 и запоминать указатель на стек при входе в следующие функции. А при выходе просто смещать указатель да и все. И не надо кучи стеков.
Я просто не могу понять как это реализовать в другом виде. Ну вот есть f3, да? Вот насоздавал я там кучу объектов, типа 1,2,3,4,5. Но вот удалять мне их потом надо фиг пойми как да еще каждый раз по-разному. Вот в первый прогон функции удаляются 4,5,1,3,2. Вот второй прогон удаляются 5,1,4,3,2. Как это будет реализовано в стеке? И стек и куча они ведь "плоские", типа лента адресов и любое удаление в порядке отличающимся от создания "рвет" эту ленту создавая "дыры" в занятой памяти. Какой такой простой алгоритм есть для того чтобы уменьшать стек при произвольном удалении объектов да еще и быстрей кучи чтобы получилось? Стек красота, когда Вы точно знаете как и что будет удаляться, тогда и данные можно пихать так, чтобы просто потом сместить указатель на вершину стека одной-двумя командами. Да и многостековость легко переносится на многокучевость. Создал на каждую функцию свою кучу — вышел из функции, потер весь блок да и вся проблема.

     2016/05/05 10:38, utkin

Потеря эффективности. Простейшие реализации функций malloc() и free() имеют длину несколько сотен строк. А уж продвинутые — тем паче длиннее.

Но дают возможность работы с объектами динамической природы. То есть это не то чтобы грех. Это просто решение других задач. От стека ведь как правило никто не отказывается — простые переменные обычно там и лежат.

Некорректная работа с памятью в куче может приводить к её утечкам. Причиной может быть как ошибки в библиотечных функциях управления памятью, так и ошибки в программе при ручном управлении.

Ну это так же "Некорректная работа с памятью в стеке может приводить к ее утечкам". Я вот как отчаянный паскалист скажу так: Программист на С++ с легкостью решает не существующие в Паскале проблемы. Откажитесь Вы от прямого доступа к памяти, да и все проблемы. Есть классы и объекты, есть динамические массивы. Зачем вот ковыряться в этих указателях? Оно вот надо только для очень узких задач. Вон в C# для этого надо специально переключаться на неуправляемый код. Вот Вам идеальное решение, раз переключились значит понимаете, что "Некорректная работа с памятью в куче может приводить к её утечкам.", то есть сами себе Буратино, что не смогли корректно составить алгоритм, а не валить все на компилятор.

Фрагментация памяти. Если «до упора» выделять память по одному байту, а потом освободить занятые блоки памяти, но не все, а через один, то память будет нарезана на множество маленьких кусочков, которые невозможно использовать. Сложные алгоритмы распределения памяти могут обходить эту проблему путём перемещения фрагментов и изменения указателей. Но это опять расходование вычислительных ресурсов.

Не знаю в какой куче память выделяется по байтно. Память выделяется поблочно. Размер блока определяет создатель системы исходя из каких-то своих измышлений (может тесты проводит, а может ему так нравится, а может ось любит давать память приложению кратно 16-ти байтам). По поводу ресурсов — да, но других решений нет. Варианта там 2 обычно. Самый простой — сразу перемещать последний блок на место освободившегося. Вариант 2 — это дефрагментация по наступлению определенного события (например, 30 процентов блоков не используются и т.д.). Вот раньше была такая частая процедура на XP — дефрагментация диска. Вот Вам прямая аналогия — диск, он ведь тоже не произвольное расположение, а лента (физически наверно спираль или круги).

Алгоритмы динамического распределения памяти либо просты, либо хороши. Более того, одни алгоритмы хорошо работают для одного класса задач, а другие — для другого.

Так и стек. Иначе бы других структур не было бы в принципе. Ни очередей, ни массивов, ни более сложных коллекций. Зачем все усложнять когда есть такой вот эффективный стек? Это ведь можно так напороться на скальпель монаха Оккама, который говорит в стиле Маяковского — если звезды на небе зажигаются, значит это кому-нибудь нужно. Иными словами, если помимо стека придумывают что-то еще, значит стек не может решить всех задач. Это я даже без всяческих тестов могу утверждать.

Некоторые алгоритмы динамического распределения памяти выделяют память быстро, но в ситуациях, когда память заканчивается и нужно обеспечить «сборку мусора», начинают «тормозить». Имея хорошее среднее время отклика, они не могут обеспечить его гарантированный минимум. Поэтому в системах реального времени используют другие алгоритмы. Они имеют гарантированное время отклика, но среднее время отклика у них выше.

Это специализация. Она не означает, что стек круче чем все остальное. Стек круче в своей области применения (иначе бы его просто не использовали). Но в других задачах круче другие структуры (иначе их бы не использовали :) ).

Ссылки на участки памяти в «куче» могут быть потеряны. В этом случае память не может быть освобождена, поскольку её адрес становится неизвестен программе. Для решения проблемы используют «умные указатели», которые хоть и решают задачу, но опять же, ценой дальнейшей потери эффективности.

Как это ссылка на участок памяти в "куче" может быть потеряна? Это что-то из области зеленых человечков. Если программист напортачил в коде, то так и надо говорить — это программист уже неделю не был на свежем воздухе и глаза у него в куче, а не ссылка там. Я выше уже написал Вам как решаются подобные проблемы — оторвать руки программисту, решающего прикладную (не системную!) задачу с помощью прямого доступа к памяти по указателям. И дело здесь не а куче, а в человеческом факторе, будете маскировать источник проблемы, будете все время бороться с ее проявлением. Нужно честно поставить диагноз — у программ проблемы с утечками памяти потому что у программистов руки из задницы растут, а язык позволяет им оттуда расти. И решение соответствующие — либо руки за спину скотчем замотать либо в языке сделать выстрел в ногу жутко утомительным занятием.

     2016/05/05 13:24, Автор сайта

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

Если Вы считаете, что пользоваться кучей в таких случаях — не грех («Десятки языков делают это!»), то Вы — сторонник развития языков программирования по второму пути (см. классификацию языков программирования в начале статьи «философия языка»). Наша же цель — сделать язык программирования первого типа, т.е. пригодного для системного программирования, выжимающий из оборудования максимум. Если есть возможность обойтись без кучи и сборки мусора для целого класса задач, то мы не можем это игнорировать.

     2016/05/05 13:45, utkin

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

Это не вопрос языка. Это вопрос реализации языка. Тут, наверно, нужно провести моделирование имеющейся проблемы. Построить стек и пытаться реализовать алгоритм предсказания уничтожения данных.

Если Вы считаете, что пользоваться кучей в таких случаях — не грех («Десятки языков делают это!»), то Вы — сторонник развития языков программирования по второму пути (см. классификацию языков программирования в начале статьи «философия языка»).

Я не то, чтобы против. Я хочу понять, что это действительно эффективно и за счет чего. Вот простой вопрос — можно ли полностью заменить кучу? Ведь по сути если нельзя, то получается, что куча и ее неэффективная (по сравнению со стеком) реализация останется. В таком случае, нужно рассматривать весь путь полностью.
Сейчас это выглядит так — мальчики налево (в стек), девочки направо (в кучу). То есть тип данных определяет, кто и где будет находится. Вы предлагаете не упростить, а усложнить алгоритм — мальчики налево (в стек), на девочках вводим новый алгоритм предсказания, а там уже по результату в стек или в кучу. В стеке быстрей, но кто будет считать время затраченное на предсказание? Или оно будет только на этапе компиляции? Тогда чем это будет отличаться от механизма, заложенного в Ява?
А максимальная эффективность очевидно, это когда кучи нет в программе вовсе. Вы же предполагаете некоторое увеличение эффективности, поскольку, как я понял, точно неизвестно, можно ли быстро и эффективно располагать динамические данные в стеке.

Наша же цель — сделать язык программирования первого типа, т.е. пригодного для системного программирования, выжимающий из оборудования максимум. Если есть возможность обойтись без кучи и сборки мусора для целого класса задач, то мы не можем это игнорировать.

В C# код есть управляемый и не управляемый. В управляемом все просто и красиво, в неуправляемом Вы сами заботитесь о проблемах. Исполнение можно комбинировать. Подумайте, может это можно прикрутить?

     2016/05/05 14:23, Автор сайта

Это вопрос и языка, и реализации. В Си не нашли возможности возвратить в стек объект переменного размера, потому язык сделали так, как могли — возвращали в стек объекты только фиксированного размера.

Да, сейчас тип объекта (а именно его размер — известный во время компиляции или нет) определяет, где он будет храниться. Есть намерение изменить этот порядок вещей. Способ хранения должен определяться исключительно дисциплиной его использования. Пример:
f (...) {ptr = конструктор объекта(...);}
Если ptr с созданным объектом должен жить дольше, чем функция f (например, при многопоточном программировании), то объект должен создаваться в куче. Если же ptr с объектом живут не дольше, чем f, то они должны храниться локально в стеке функции f. Решение о месте выделения памяти под объект должно приниматься системой владения/заимствования объектов. Над этим ещё надо думать. Можно обратить внимание на эту концепцию в языке Rust.

     2016/05/05 15:31, utkin

Если ptr с созданным объектом должен жить дольше, чем функция f (например, при многопоточном программировании), то объект должен создаваться в куче. Если же ptr с объектом живут не дольше, чем f, то они должны храниться локально в стеке функции f. Решение о месте выделения памяти под объект должно приниматься системой владения/заимствования объектов.

У Вас могут возникнуть проблемы с функциями высшего порядка (это когда функция в качестве аргумента получает другую функцию или возвращает ее в качестве аргумента). Наверно все таки тут стоит строить какой-то макет/модель. И отрабатывать уже на ней.

Можно обратить внимание на эту концепцию в языке Rust.

Где его описание на русском?

     2016/05/05 15:43, Автор сайта

Да, концепция требует проработки. Вот как это в Rust: http://rurust.github.io/rust_book_ru/src/lifetimes.html

     2016/05/06 08:57, utkin

За источник спасибо.

     2016/05/06 11:20, Автор сайта

Не за что. Он же из Википедии взят :)

     2016/05/06 15:21, utkin

Про ссылку — там черным по белому написано о ссылках на кучу и сборку мусора по выходу из блока функции. Можно какую угодно терминологию наводить, но суть-то та же :).
Пример, где после присваивания первоначальный вектор нельзя присваивать, вообще убил. Попытка контроля ссылок по выдачи исключения. Типичный Access Violation в Дельфи.

     2016/05/06 15:40, utkin

Вообще Rust разочаровал, тот же Ява, только компилятор и со своей терминологией. Типажи ВЕЗДЕ интерфейсы, то есть синтаксический сахар.
Модификатор mut(able):

Если вы случайно забыли указать mut и изменили связывание, компилятор заметит это, и сообщит вам, что вы попытались изменить не то, что собирались.

А если я случайно поставил mut там, где он быть не должен? А если я действительно ДОЛЖЕН это менять и действительно просто забыл поставить mut? Сомнительная эффективность защиты очевидна. Почему бы вместо let x=5; не написать правду? const x=5;

Область видимости и затенение это ЕСТЕСТВЕННОЕ поведение в других языках программирования, а в связке с mut вообще подозрительны.

И так много чего еще. В общем-то первое впечатление — попытка из Си сделать Хаскелл.

     2016/05/07 11:12, Автор сайта

Да, в Rust объекты, чей размер известен только во время исполнения, располагаются в куче. Но это не уменьшает проблем, связанных с указателями. Можно, конечно, положиться на «умные» указатели и системы сборки мусора. Но чем больше забот мы перекладываем на программы, которые сами следят за собой, тем дальше мы отдаляемся от системного программирования. Но в тех же системах реального времени автоматическая сборка мусора просто не приемлема. Rust пытается это решить. Не нравится, как он это делает? Отлично, у нас есть шанс сделать лучше! Если бы языки были идеальны, то нам с Вами не нашлось бы работы :)

     2016/05/11 09:47, utkin

Не нравится, как он это делает?

Мне кажется он слегка жульничает, когда так много говорится в новой форме о старых дырах :). Насчет оптимального решения — его наверно нет вообще. Поэтому и идет специализация языков программирования на сферы использования.
Насчет неизменяемости, там слишком много внимания уделяется этому вопросу, в конце концов, если бы все было бы неизменяемым, то и программы нужны были только на один раз — посчитал и все на этом, если исходные данные неизменяемы, то и результат очевидно не поменяется. Если же говорить о стеке, то идеальное решение тоже не очевидно, есть же Форт, на нем все и закончилось бы, если все было бы легко и просто. Тут 2 крайности — эффективность и выразительность. Выразительные средства не эффективны и компилировать их (да даже с кучей) весьма не просто. Эффективные средства не выразительны. Вот где там середина, которая всем бы нравилась?

     2016/05/11 11:13, Автор сайта

Могу сказать твёрдо и однозначно, что концепция владения и заимствования в Rust переусложнена и в значительной части случаев она просто не нужна. Ведь какие проблемы решает эта концепция? Она позволяет разрешить коллизии, связанные с существованием объектов и их уничтожением. Но эти проблемы существуют при многопоточном программировании. А при однопоточном программировании их просто нет. Возьмём такой простейший код: y=sin(x). Зачем объект x передавать во владение функции sin? Ведь код в этом случае работает строго по очереди: либо код внутри sin, либо код до и после этой функции. Никаких коллизий тут быть не может, объекты возникают и исчезают строго по дисциплине LIFO. Ну зачем тут нужно владеть объектами?

Выразительные средства не эффективны ... Эффективные средства не выразительны. Вот где там середина, которая всем бы нравилась?

Наверное, это асимптотические функции :) В золотой средине графики этих функций не существуют. Они стремятся к этой точке, но не пересекают.

     2018/05/25 00:20, Александр Коновалов aka Маздайщик

Хочу рассказать об одном интересном моменте, о котором многие не знают/не задумываются. Оператор new в C# работает зачастую быстрее, чем в C++. Почему?

В C++, чтобы выделить память, нужно в куче найти свободный фрагмент подходящего размера и отделить от него участок нужного размера (т.е. оставить в куче остаток от найденного фрагмента). Точные действия зависят от реализации кучи (простой двусвязный список, близнецовый метод и т.д.), но понятно, что нужно какое-то количество процессорных циклов. Причём неопределённое, поскольку на поиск требуется время, зависящее от размера кучи.

В C# выделение памяти выполняется инструкцией top += sizeof(T). Т.е. указатель кучи просто сдвигаем вперёд на размер объекта. Одна машинная инструкция.

Плата за эту простоту хорошо известна: сборка мусора. Чтобы, не задумываясь, выделять объекты один за другим, нужно при каждой сборке мусора уплотнять кучу. А это не только перемещение объектов в памяти, но и правка всех указателей, которые ссылаются на перемещаемые объекты.

Конечно, там используются не просто алгоритмы «утрамбовки», а копирующие сборщики мусора по поколениям. Т.е. когда «нулевое» поколение заполнилось, все живые объекты из него перекладываются в другую область памяти, «первое» поколение, а участок «нулевого» снова свободен. Когда заполняется первое — перекладываются объекты во второе. И т.д.

А в случае явного delete в C++ можно добиться удаления объекта за константное время.

     2018/05/26 00:47, Автор сайта

По-моему, есть какие-то методы распределения памяти, которые в среднем более медленны, но гарантируют минимальное время выделения и освобождения памяти. И при этом исключают фрагментацию памяти.

     2018/05/27 16:41, Александр Коновалов aka Маздайщик

Без уплотняющего сборщика мусора фрагментацию исключить нельзя. По крайней мере, я не представляю как. Но можно уменьшить её степень.

Например, алгоритм двойников (https://en.wikipedia.org/wiki/Buddy_memory_allocation) позволяет снизить фрагментацию (при достаточно быстрой аллокации и деаллокации) ценой расхода памяти — участки могут выделяться только размера, пропорционального степени двойки.

Написать отзыв

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

Авторизация

Регистрация

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

Карта сайта


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Комментарии

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

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

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

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

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

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

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

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

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

Циклы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Компилятор

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

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

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

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

Последние комментарии

2018/12/16 17:17 ••• Геннадий Тышов
✎ Программирование без программистов — это медицина без врачей

2018/12/07 08:57 ••• Автор сайта
✎ Почему обречён язык Форт

2018/12/07 08:36 ••• Автор сайта
✎ Нужны ли беззнаковые целые?

2018/12/03 13:51 ••• kt
✎ Экстракоды при синтезе программ

2018/11/30 17:56 ••• Freeman
✎ Изменение приоритетов операций

2018/11/30 17:20 ••• Автор сайта
✎ Почему языки с синтаксисом Си популярнее языков с синтаксисом Паскаля?

2018/11/26 14:23 ••• Автор сайта
✎ Так ли нужны операции «&&», «||» и «^^»?

2018/11/18 15:21 ••• Freeman
✎ Устарел ли текст как форма представления программы

2018/11/17 03:28 ••• Comdiv
✎ Изменение длины объекта в стеке во время исполнения

2018/11/16 12:53 ••• Автор сайта
✎ Помеченные комментарии

2018/11/11 14:01 ••• Александр Коновалов aka Маздайщик
✎ Нерабочий код

2018/11/11 13:39 ••• Александр Коновалов aka Маздайщик
✎ О русском языке в программировании