Куча против Стек для разработчиков Delphi

Вызовите функцию «DoStackOverflow» один раз из ваш код и вы получите EStackOverflow Delphi выдает ошибку с сообщением «переполнение стека».


функция DoStackOverflow: integer;

начать

 результат: = 1 + DoStackOverflow;

конец;

Что это за «стек» и почему происходит переполнение с использованием приведенного выше кода?

Таким образом, функция DoStackOverflow рекурсивно вызывает себя - без «стратегии выхода» - она ​​просто продолжает вращаться и никогда не завершается.

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

Вы идете дальше, и вы никогда не оглядываетесь назад, не заботясь об ошибке / исключении, как это теперь решено.

Тем не менее, остается вопрос: что это за стек и почему переполнение?

Память в ваших приложениях Delphi

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

instagram viewer
бесплатно то, что вы создаете.

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

Вы попадете в точку, где вы будете читать, в справке, что-то вроде «Локальные переменные (объявленные в процедурах и функциях) находятся в приложении стек." а также Классы являются ссылочными типами, поэтому они не копируются при присваивании, они передаются по ссылке и распределяются по куча.

Итак, что такое «стек» и что такое «куча»?

Стек против отвал

Запуск вашего приложения в WindowsЕсть три области в памяти, где ваше приложение хранит данные: глобальная память, куча и стек.

Глобальные переменные (их значения / данные) хранятся в глобальной памяти. Память для глобальных переменных зарезервирована вашим приложением при запуске программы и остается выделенной до ее завершения. Память для глобальных переменных называется «сегмент данных».

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

Стек и куча - место динамического выделения памяти: когда вы создаете переменную для функции, когда вы создаете экземпляр класса, когда вы отправляете параметры в функцию и используете / передаете ее результат значение.

Что такое стек?

Когда вы объявляете переменную внутри функции, память, необходимая для хранения переменной, выделяется из стека. Вы просто пишете «var x: integer», используете «x» в своей функции, и когда функция завершается, вас не заботит ни распределение памяти, ни освобождение. Когда переменная выходит из области видимости (код выходит из функции), память, которая была занята в стеке, освобождается.

Память стека выделяется динамически с использованием подхода LIFO («последний пришел первым - ушел»).

В Delphi программы, стековая память используется

  • Переменные локальной процедуры (метод, процедура, функция).
  • Обычные параметры и возвращаемые типы.
  • Функция Windows API звонки.
  • Записи (вот почему вам не нужно явно создавать экземпляр типа записи).

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

Объем памяти стека по умолчанию достаточно велика для ваших (как бы сложных) программ Delphi. Значения «Максимальный размер стека» и «Минимальный размер стека» в параметрах компоновщика для вашего проекта задают значения по умолчанию - в 99,99% вам не потребуется изменять это.

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

При использовании локальной памяти из стека локальные переменные не инициализируются при объявлении. Объявите переменную "var x: integer" в некоторой функции и попробуйте прочитать значение при входе в функцию - x будет иметь какое-то "странное" ненулевое значение. Поэтому всегда инициализируйте (или устанавливайте значение) локальные переменные, прежде чем читать их значение.

Благодаря LIFO операции со стеком (выделение памяти) выполняются быстро, так как для управления стеком требуется всего несколько операций (push, pop).

Что такое куча?

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

В программах Delphi куча памяти используется / когда

  • Создание экземпляра класса.
  • Создание и изменение размера динамических массивов.
  • Явное выделение памяти с использованием GetMem, FreeMem, New и Dispose ().
  • Использование строк ANSI / wide / Unicode, вариантов, интерфейсов (управляется автоматически Delphi).

Куча памяти не имеет приятного расположения, где будет какой-то порядок распределения блоков памяти. Куча выглядит как банка мрамора. Распределение памяти из кучи является случайным, блок отсюда, чем блок оттуда. Таким образом, операции с кучей немного медленнее, чем в стеке.

Когда вы запрашиваете новый блок памяти (т. Е. Создаете экземпляр класса), менеджер памяти Delphi позаботится об этом за вас: вы получите новый блок памяти или использованный и сброшенный.

Куча состоит из всей виртуальной памяти (RAM и дисковое пространство).

Выделение памяти вручную

Теперь, когда все в памяти ясно, вы можете безопасно (в большинстве случаев) игнорировать вышесказанное и просто продолжать писать программы на Delphi, как вы это делали вчера.

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

«EStackOverflow» (с начала статьи) возник, потому что при каждом вызове DoStackOverflow из стека использовался новый сегмент памяти, и у стека есть ограничения. Так просто, как, что.

instagram story viewer