Delphi предоставляет только ограниченные возможности для размещения объектов из любого места, кроме основного диспетчера памяти. Для этого вам необходимо переопределить метод класса NewInstance
. Это метод, который конструктор вызывает для размещения нового экземпляра класса. Стороной уничтожения является FreeInstance
.
Переопределите эти методы и позвоните по номеру HeapAlloc
и HeapFree
. Тем не менее, количество байтов для выделения не определяется SizeOf
. SizeOf
сообщает вам размер ссылки на объект, который всегда является SizeOf(Pointer)
. Вам нужен размер экземпляра, который предоставляется методом InstanceSize
класса.
Хотя вы можете переопределить методы, чтобы использовать выбранную стратегию памяти распределения, вы, вероятно, не будете удовлетворены результатами, потому что есть несколько проблем:
Метод NewInstance
Безразлично» t принять какие-либо параметры, поэтому вам не следует указывать класс , из которого куча выделяется. У вас может быть одна глобальная куча или куча для каждого класса, но вы не можете выбрать, какую кучу использовать для каждого экземпляра отдельно.
Метод NewInstance
разделяется всеми экземплярами данного класса, так что нет никакого способа, чтобы выделить только некоторые экземпляров на вашей специальной куче и выделить остальные от менеджера по памяти по умолчанию. Это в основном другой способ формулировки предыдущей проблемы.
Вы не можете модифицировать это в существующие классы, поэтому вы можете выделить TMyStringList
, но не TStringList
. (Ну, вы можете , но это требует исправления VMT для каждого класса, который никогда вообще никогда не рекомендуется.)
Есть несколько проблем с кодом вы пробовали. Во-первых, вы никогда не выделяли TStringList
. Вы указали указатель на тот, который, как я упоминал выше, составляет SizeOf(Pointer)
байт. Недостаточно памяти для хранения экземпляра TStringList
.
Вам вообще не нужен ^TStringList
. Вы могли бы назначили вашу выделенную память непосредственно к TStringList
переменной SL
:
SL := HealAlloc(Handle, 0, TStringList.InstanceSize);
Обратите внимание, как я настроил размер.
Это все еще не достаточно, хотя, потому что в то время как это имеет выделено часть памяти, он не построен объект. Вам нужно будет вызвать конструктор.
SL.Create;
Обратите внимание, что конструктор будет выделять больше памяти для хранения списка строк, а также выделить еще больше памяти для хранения содержимого строки. Эти распределения памяти не будут отображаться в куче. Они перейдут к менеджеру памяти по умолчанию, как всегда.
Уничтожение объекта будет еще одной проблемой. Вам нужно вызвать деструктор, чтобы освободить строку строк, но если вы это сделаете, деструктор также попытается освободить память объекта. Он будет использовать диспетчер памяти по умолчанию, чтобы освободить его, но поскольку вы не использовали диспетчер памяти по умолчанию для выделения объекта TStringList
, диспетчер памяти будет генерировать исключение EInvalidPointer
.
Delphi не предоставляет возможности уничтожить объект, не отпуская также соответствующую память. То есть вы не можете позвонить по номеру Destroy
, не позвонив по номеру FreeInstance
, но TStringList.FreeInstance
позвонит по номеру FreeMem
, а не HeapFree
.
Я рекомендую сделать шаг назад от текущей задачи и повторно рассматривая проблему, которую вы целились решить с вашей идеей отдельной кучи для определенных объектов. Могут быть лучшие решения, которые не требуют больших усилий для борьбы с тем, что предназначены для ваших инструментов.
Что именно вы пытаетесь достичь здесь? 'SL' уже является указателем на экземпляр' TStringList', поэтому 'P' является указателем * на указатель на экземпляр TStringList *. –
@KenWhite Я пытаюсь использовать TStringList? – user5531072
Это кажется чреватым опасностью. Похоже, что вы действительно хотите, это другой менеджер памяти для Delphi. То, что вы пытаетесь сделать, не будет работать. Подумайте, что даже если вам удастся создать 'TStringList' в вашей новой куче, строки внутри него будут по-прежнему жить на общей куче, поэтому любой спор, который вы пытаетесь избежать, будет сбой точно так же (если вы это делаете пытаясь сделать). –