- - * - WhiteUnicorn - * - -




* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >


2964:Managing Data Segment Size

KEYWORDS: data segment size AREA: General

Managing Data Segment Size

 	The "Data Segment too large" error occurs in Delphi 16
bit applications when the size of static data, stack and local
heap are larger than the 64k application limit imposed by
Windows. This document discusses how to identify and measure
portions of your code that consume memory in the data segment,
and how to manage this limited resource.


What does the data segment consist of?
--------------------------------------
Task header: 	16 bytes of various Windows system information
Static data: 	Contains global variables and typed constants.
Stack:  	Stores local variables allocated by procedures
		and functions.  The default stack size is 16k
		and can be modified in the
		Options|Project|Linker page.
Local heap: 	Used by Windows for temporary storage and
		defaults to 8k. Do not set the local heap to 0.
		Windows may expand this area of memory if
		necessary.


How do I measure total data segment size?
-----------------------------------------
	To get the size of a 16 bit Delphi application static
data, stack and local heap for a project, compile the project
and select the Delphi menu item Compile|Information.  The dialog
will list the following, given a new project with one form:

Source compile:	12 lines
Code size:		128981 bytes
Data size:		3636 bytes
Stack size:		16384 bytes
Local Heap size:	8192 bytes

	A Delphi application starts with the overhead of static
data declared in units that provide the applications initial
functionality. If the only global variable is the form name,
the application will still consume at least 3,636 bytes.
Adding a second form increases the datasize to only 3640 --
an increase of only the size of the global variable needed to
declare a second form.

var
  Form2: TForm2; { 4 byte pointer }

	The total data segment size, (the sum of static data,
stack and local heap) is 28,212 bytes:

Data size:		 3,636
Stack size:		16,384
Local Heap size:	 8,192
------------------------------
		        28,212

What portions of my project increase data size?
-----------------------------------------------
-- Variables declared within the interface and implementation
   sections.
-- Typed constants declared anywhere within the application.
   An example of a typed constant declaration:

	const
	  MyConst: integer = 100;

	Units declared in the Uses clause and components
contain code that may hvae global variables or typed constants.
For instance, a TBitBtn adds 180 bytes when added to a project,
where at least 132 bytes are accounted for by typed constants
and global variables within the Buttons.Pas unit.  Adding 10
more TBitBtns to the project does not increase the project
size beyond the initial 180 byte increase.
	
The following sample unit includes comments describing memory
usage:


unit Test;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls;

{ Functions used from the units may have global variables
  and typed constants that will increase the size of the
  data segment. }

type
   { Class objects are stored on the global heap, not the data
     segment}
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  public
   { MyInteger and MyString are stored
     on the global heap. }
    MyInteger: Integer;
    MyString: String;	
  end;

const
{ MyConst is a typed constant and is stored in
  static data portion of the data segment.
  Minimize the number of typed constants. }
  MyConst: integer = 23; 	

var
{ Form1 is a global variable - stored in the static
  data portion of the data segment.  You should minimize
  the number and size of global variables. Form1 is
  pointer and uses only four bytes. }
  Form1: TForm1;		 	
{ MyGlobalString will consume 256 bytes even if the
  string is only a few characters long. }
  MyGlobalString: string;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
{ MyLocal is a local variable and is not stored
  in the data segment. }
  MyLocal: String; 	
begin
  MyLocal := 'Test application';
  Label1.Caption := MyLocal
end;

end.



What is the impact of components on the data size?
--------------------------------------------------
Here is a list of components from the Standard, Additional,
Data Access, and Data Control(partial list) pages of the
component pallette.  The list shows the compile size after
added a single instance of the component to a new project.
In descending order by data size usage:

Component	App	Bytes
		in 	Over
		bytes	3,636
		
table		4272	636
batchmove	4272	636
storedproc	4258	622
query		4250	614
database	4036	400
datasource	3886	250
outline		3838	202
bitbtn		3816	180
stringgrid	3794	158
drawgrid	3790	154
maskedit	3762	126
memo		3750	114
report		3722	86
listbox		3704	68
edit		3694	58
tabset		3692	56
combobox	3674	38
scrollbar	3654	18
button		3652	16
checkbox	3652	16
radiobutton	3652	16
radiogroup	3652	16
panel		3650	14
label		3648	12
speedbutton	3646	10
header		3644	8
scrollbox	3644	8
notebook	3638	2
menu		3636	0
groupbox	3636	0
tabbednotebook	3636	0
image		3636	0
shape		3636	0


How do I manage data segment size?
----------------------------------
1) Avoid declaring global variables or typed constants,
   particularly large arrays. Instead, declare a type and
   a pointer to that type. Then use memory management
   routines such as Getmem to allocate memory from the
   global heap.
   This reduces the resource hit on the data segment to the
   4 bytes used by the pointer variable. See code sample below.
2) Be aware of the impact of components. See above.
3) If you have a large number of strings, or arrays of strings,
   allocate these dynamically.  Note: strings default to 255 in
   length -- declare as a specific size where possible:
   (i.e. MyShortString: string[20]).
4) A TStringList object can be used to create and manipulate
   large numbers of strings.
5) The Pchar type, "pointer to a string", can be used to
   dynamically create and manipulate character strings using
   little data segment space. See online help under
   "String-handling routines (Null-terminated)".
6) Information on memory issues is available in Object Pascal
   Language Guide, OBJLANG.ZIP and can be downloaded from
   Compuserve, DELPHI forum, and the World Wide Web,
   www.borland.com/TechInfo/delphi/whatsnew/dwnloads.html.


Alternative to global declaration of a large structure
------------------------------------------------------

Here's an example that will waste 32 bytes of data segment,
followed by a second example using only 4 bytes, and
accomplishes essentially the same task.

1)
  { Declaring TMyStructure causes no change
    in the data segment size. }
  TMyStructure = record
    Name: String[10];
    Data: array[0..9] of Integer;
  end;

 var
   Form1: TForm1;

  { MyStructure declaration causes a 32 byte
    increase:
    Mystructure pointer =  1 byte
      Name = 11 bytes (10 chars + length byte)
      Data = 20 bytes (10 * 2 bytes per integer)
  }
  MyStructure: TMyStructure;

2)
  { Declaring TMyStructure causes no change
    in the data segment size. }
    PMyStructure = ^TMyStructure;
    TMyStructure = record
      Name: String[10];
      Data: array[0..9] of Integer;
    end;

    var
      Form1: TForm1;
      { MyDataPtr causes 4 byte increase
        for the pointer variable. }
      MyDataPtr: PMyStructure;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  { Here, resources are taken from the heap. }
  New(MyDataPtr);
  MyDataPtr.Name := 'Fred';
  MyDataPtr.array[0] := 560;
  Dispose(MyDataPtr);
end;


You can also put a variable declaration within a class:

type
  TMyBigArray = array[1..100] of string

  TForm1 = class(TForm)
  public
    { This declaration has no impact on data segment size. }
    MyBigArray: TMyBigArray;
  end;

var
  { This declaration increases data segment by 25,600 bytes. }
  MyOtherBigArray: TMyBigArray;

        TI



* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >



- - * - Anastasija aka WhiteUnicorn - * - - LJLiveJournal
PFPhotoFile