Ошибка "Data Segment too large" (сегмент данных слишком велик) возникает в Delphi 16-битных приложениях в случае, когда размер статических данных, стека и локальной кучи превышает предел приложений Windows, установленный в 64К. В данном совете обсуждается тема идентификации и изменения части вашего кода, которая поглощает память в сегменте данных, и как, собственно, управлять этим ограниченным ресурсом.
Из чего состоит сегмент данных?
Task header: 16 байт различной системной информации Windows (заголовок задачи) Static data: Содержит глобальные переменные и типовые (статические константы данные) Stack: Хранит локальные переменые, распределенные (стек) процедурами и функциями. Размер стека по по умолчанию 16К и может быть изменен на странице Options|Project|Linker. Local heap: Используется Windows для временного хранения и (локальная по умолчанию имеет размер 8К. Не устанавливайте куча) разнер локальной кучи, равным 0. Windows при необходимости может увеличить данную область. Как мне узнать полный размер сегмента данных?
Для того, чтобы получить размер статических данных 16-битного приложения Delphi, стека и локальной кучи для проекта, скомпилируйте проект и выберите в меню Delphi пункт Compile|Information. Для нового проекта с одной формой диалог покажет следующую информацию:
Source compile: 12 lines (скомпилировано 12 строк исходного кода) Code size: 128981 bytes (размер кода 128981 байт) Data size: 3636 bytes (размер данных 3636 байт) Stack size: 16384 bytes (размер стека 16384 байт) Local Heap size: 8192 bytes (размер локальной кучи 8192 байт) Приложение Delphi начинается с объявления в модуле статических данных, тем самым обеспечивая функциональную инициализацию. Если единственная глобальная переменная является именем формы, то приложение занимает уже, по крайней мере, 3,636 байт. Добавляя вторую форму, размер увеличивается только до 3640 -- добавляется только размер глобальной переменной, необходимой для объявления второй формы.
var Form2: TForm2; { 4-х байтный указатель } |
constMyConst: integer = 100; |
unit Test; interface usesSysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; { Используемые в модуле функции могут иметь глобальные переменные и типизированные константы, которые увеличивают размер сегмента данных. } type{ Объекты класса хранятся в глобальной куче, не в сегменте данных}TForm1 = class(TForm)Label1: TLabel;Button1: TButton;procedure Button1Click(Sender: TObject);public{ MyInteger и MyString хранятся в глобальной куче. }MyInteger: Integer;MyString: String;end; const{ MyConst - типизированная константа и сохраняется в области статических данных сегмента. Минимизируйте количество типизированных констант. }MyConst: integer = 23; var { Form1 - глобальная переменная и хранится в области статических данных сегмента. Вы должны минимизировать число и размер глобальных переменных. Form1 является указателем и занимает только четыре байта. } Form1: TForm1;{ MyGlobalString занимает 256 байт, даже если строка состояла бы всего из нескольких символов. } MyGlobalString: string; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject);var{ MyLocal - локальная переменная и не хранится в сегменте данных. }MyLocal: String;beginMyLocal := 'Тестовое приложение';Label1.Caption := MyLocalend; end. |
{ Объявление TMyStructure не вызовет никаких изменений в размере сегмента данных. }TMyStructure = recordName: String[10];Data: array[0..9] of Integer;end; varForm1: TForm1; { Объявление MyStructure вызовет увеличениеразмера сегмента памяти на 32 байта:указатель Mystructure = 1 байтName = 11 байт (10 символов + байт длины)Data = 20 байт (10 * 2 байт на целое)}MyStructure: TMyStructure; |
{ Объявление TMyStructure не вызовет никаких изменений в размере сегмента данных. }PMyStructure = ^TMyStructure;TMyStructure = recordName: String[10];Data: array[0..9] of Integer;end; varForm1: TForm1;{ MyDataPtr вызывает увеличение на 4 байтадля размещения указательной переменной. }MyDataPtr: PMyStructure; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject);begin{ Здесь ресурсы берутся из кучи. }New(MyDataPtr);MyDataPtr.Name := 'Fred';MyDataPtr.array[0] := 560;Dispose(MyDataPtr);end; |
typeTMyBigArray = array[1..100] of string TForm1 = class(TForm)public{ Это объявление не повлияет на размер сегмента данных. }MyBigArray: TMyBigArray;end; var{ Это объявление увеличивает сегмент данных на 25,600 байт. }MyOtherBigArray: TMyBigArray; |