Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11642
Последний выпуск: 19.06.2015

Разделяемая память в FPC (Free Pascal)

Автор: Иван Шихалев
Источник: http://freepascal.ru/

Проблема

При использовании динамических библиотек приходится соблюдать ограничение на типы данных, которые могут передаваться в параметрах процедур и функций. Если попытаться активно передавать динамические массивы и/или длинные строки (тип ansistring), то рано или поздно возникнет AV - ошибка 216. Кроме того, приходится следить, чтобы процедуры выделения/освобождения динамической памяти вызывались из одного и того же модуля.

При написании сложной многомодульной программы эти ограничения весьма неприятны.

Причины

Дело в том, что Free Pascal для распределения динамической памяти использует не функции операционной системы, а свои собственные, что позволяет значительно ускорить процесс. Однако это приводит к тому, что данные о состоянии памяти, выделенных и свободных блоках и т.д. хранятся в глобальных переменных исполняемого модуля. Таким образом, пул памяти динамической библиотеки отделен от пула памяти вызывающего ее приложения. А длинные строки и динамические массивы как раз и используют (неявно) динамическую память.

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

Решение

К счастью, Free Pascal позволяет программисту заменить стандартный менеджер памяти любым другим. Для этого используется процедура SetMemoryManager().

Итак, чтобы все модули работали с одним пулом динамической памяти следует выделить один, который за эту память будет отвечать, а в остальных на него сослаться. Конкретно это делается так: пишется библиотека, которая экспортирует функцию, возвращающую ее менеджер памяти; пишется модуль, который в секции инициализации устанавливает этот менеджер памяти в качестве своего; во всех исполняемых файлах большого проекта используется данный модуль. При этом важно, чтобы в первичном файле (том, который начинается с program или library), модуль подключения был первым в списке uses - это нужно для того, чтобы менеджер памяти был установлен до инициализации прочих модулей.

Реализуется это просто:

Библиотека

{$IFDEF WIN32}
 {$APPTYPE GUI}
{$ENDIF WIN32}
{$MODE OBJFPC}
{$SMARTLINK OFF}

library fpMem;

procedure GetMemMan (out MemMan : TMemoryManager); stdcall; export;
 begin
 GetMemoryManager (MemMan)
 end;

exports
  GetMemMan name 'GetSharedMemoryManager';

end.
Модуль подключения
{$MODE OBJFPC}
{$SMARTLINK OFF}

unit SharedMemory;

interface

implementation

procedure GetMemMan (out MemMan : TMemoryManager); stdcall; 
          external 'fpmem' name 'GetSharedMemoryManager';

var
  MemMan : TMemoryManager;

initialization
 GetMemMan (MemMan);
 SetMemoryManager (MemMan)
end.

Примечание

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

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог