Delphi memory operation function 1-2: allocate memory to array pointers

Source: Internet
Author: User

Delphi memory operation function 1-2: allocate memory to the array pointer

Category: Delphi font size: large, medium, small

GetMem
AllocMem
ReallocMem
FreeMem

GetMemory
ReallocMemory
FreeMemory

New
Dispose

NewStr
DisposeStr

StrNew
StrAlloc
StrDispose

GlobalAllocPtr
GlobalFreePtr

WideStrAlloc
AnsiStrAlloc
StrDispose

Move
MoveMemory
CopyMemory
ZeroMemory
FillMemory
FillChar

StrBufSize

Allocate memory to character pointers (pchar, pwidechar, pansichar). The best choice is stralloc.

Although stralloc eventually calls getmem, stralloc adds four management bytes (record length) required by Delphi before the pointer ).

The memory allocated by stralloc is released using strdispose and the size is obtained using strbufsize.

Can I release it with freemem? In this way, four bytes are released.

This type of pointer is generally used for API function parameters, such as obtaining the window title:

var
p: PChar;
begin
p := StrAlloc(256);
GetWindowText(Handle, p, StrBufSize(p));
ShowMessage(p); {Form1}
StrDispose(p);
end;

Stralloc calls widestralloc and ansistralloc based on different parameters (pwidechar and pansichar), so we can directly use these two functions (which also needs to be released using strdispose ), however, it is not necessary to use them. Use stralloc to specify the parameter type.

It is also convenient to allocate memory to character pointers. For example:

// Obtain the Windows directory
VaR
Buf: array [0 .. max_path] of char;
Begin
Getwindowsdirectory (BUF, length (BUF ));
Showmessage (BUF); {C: \ WINDOWS}
End;

The array memory is not applied for by ourselves, and will be automatically released by the system. Remember: as long as the memory is manually applied, it must be manually released.

We apply for memory for the character pointer mainly to accept data in the API. If we want to assign the constant value directly, the system will automatically allocate the memory, for example:

VaR
P: pchar;
Begin
P: = 'in case of Delphi blog ';
Showmessage (p); {in case of a Delphi blog}
End;

Of course, we can also use this method to apply for memory, which is stupid, for example:

// Obtain the system directory
VaR
P: pchar;
Begin
P: = pchar (stringofchar (char (0), 256); {repeat an empty character for 256 times into a string and convert it to pchar}
Getsystemdirectory (p, strbufsize (p ));
Showmessage (p); {c: \ windows \ system32}
End;

If the character pointer required by the API function is for input, you do not need to apply for memory, for example:

// Set the window title
VaR
P: pchar;
Begin
P: = 'new window title ';
Setwindowtext (handle, P );
End;

// You can also directly assign a constant
Begin
MessageBox (handle, 'prompt information', 'title', mb_ OK );
End;

// If it is a variable or constant of a string, it needs to be converted.
VaR
STR: string;
Begin
STR: = 'in case of Delphi blog ';
Textout (canvas. Handle, 10, 10, pchar (STR), length (STR ));
{Output text on the form. This Code cannot be in the oncreate event}
End;

Now I have used stralloc, strdispose, widestralloc, ansistralloc, and strbufsize functions.

There are also newstr, disposestr, strnew, and strdispose.

Start with newstr and disposestr (they are a pair );
Newstr creates another pansistring Based on ansistring. However, this is compatible and is not recommended in Delphi.
All functions that are no longer recommended are labeled with deprecated and displayed in gray in the code prompt.
Actually, you can use @ to obtain string pointers. Of course they are not needed at all.

Another strnew; strnew can be used to create another character pointer, for example:

VaR
P1, p2: pchar;
Begin
P1: = 'delphi ';

P2: = strnew (P1 );
Showmessagefmt ('% s, % s', [p1, p2]); {Delphi, Delphi}

P1: = '000000 ';
Showmessagefmt ('% s, % s', [p1, p2]); {2009, Delphi}

Strdispose (P2); {release your application}
End;

However, the existence of strnew is of little significance. We can perform the above operations more simply:

var
p1,p2: PChar;
begin
p1 := 'Delphi';
p2 := p1;
ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}
p1 := '2009';
ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi}
end;

Static arrays are allocated with memory when declared, for example:

VaR
Arr1: array [0 .. 255] of char;
Arr2: array [0 .. 255] of integer;
Begin
Showmessagefmt ('array sizes: % d, % d', [sizeof (arr1), sizeof (arr2)]);
{Array size: 512, 1024}
End;

For static array pointers, although no memory is allocated at the declaration, the amount of memory allocated by this pointer is fixed.

In this case, we should use new and dispose to allocate and release memory. For example:

Type
Tarr1 = array [0 .. 255] of char;
Tarr2 = array [0 .. 255] of integer;
VaR
Arr1: ^ tarr1;
Arr2: ^ tarr2;
Begin
New (arr1 );
New (arr2 );

Arr1 ^: = 'in case of Delphi blog ';
Showmessagefmt ('% S % s', [arr1 ^ [0], arr1 ^ [1]); {In case}
// Showmessagefmt ('% S % s', [arr1 [0], arr1 [1]); {This can also be done}

Arr2 [low (arr2 ^)]: = low (integer); {minimum value assigned to the first element}
Arr2 [high (arr2 ^)]: = maxint; {the first element has a maximum value}
Showmessagefmt ('% d, % d', [arr2 [0], arr2 [255]); {-2147483648,214 7483647}

Dispose (arr1 );
Dispose (arr2 );
End;

// Modify the following example:
Type
Tarr1 = array [0 .. 255] of char;
Tarr2 = array [0 .. 255] of integer;
Parr1 = ^ tarr1;
Parr2 = ^ tarr2;
VaR
Arr1: parr1;
Arr2: parr2;
Begin
New (arr1 );
New (arr2 );

Arr1 ^: = 'in case of Delphi blog ';
Showmessagefmt ('% S % s', [arr1 [0], arr1 [1]);

Arr2 [low (arr2 ^)]: = low (integer );
Arr2 [high (arr2 ^)]: = maxint;
Showmessagefmt ('% d, % d', [arr2 [0], arr2 [255]); {-2147483648,214 7483647}

Dispose (arr1 );
Dispose (arr2 );
End;

To allocate memory to pointers of known sizes, we should use new. The above example is about static array pointers. The same is true for the struct (record) Pointers mentioned later.

The new function also calls getmem, but we do not need to specify the size.

But this is not suitable for dynamic arrays, but it should be enough to allocate the memory setlength to the dynamic array, for example:

var
arr: array of Integer;
begin
SetLength(arr, 3);

arr[0] := Random(100);
arr[1] := Random(100);
arr[2] := Random(100);

ShowMessageFmt('%d,%d,%d', [arr[0],arr[1],arr[2]]); {0,3,86}
end;

How can we allocate memory to pointers to dynamic arrays? In fact, the dynamic array variable itself is a pointer, so don't wrap it around and give it a pointer.

However, the idea is that we can convert a non-type pointer to a dynamic array type, for example:

Type
Tarr = array of integer;
VaR
P: pointer;
Begin
Getmem (p, 3 * sizeof (integer); {space allocated to accommodate 3 integers}

{This is the same size as the Tarr of the three elements, but type conversion is required}
Tarr (p) [0]: = random (1, 100 );
Tarr (p) [1]: = random (100 );
Tarr (p) [2]: = random (1, 100 );

Showmessagefmt ('% d, % d, % d', [Tarr (p) [0], Tarr (p) [1], Tarr (p) [2]); {0, 3, 86}

Freemem (P );
End;

Getmem and freemem are used here. It is quite common to allocate a non-type pointer. It can be a pointer of other types, but it is not necessarily the best solution, for example:

// Obtain the window title (it is obviously better to use the stralloc mentioned earlier)
VaR
P: pointer;
Begin
Getmem (p, 256 );
Getwindowtext (handle, P, 256 );
Showmessage (pchar (p); {form1}
Freemem (P );
End;

Getmemory and freememory should be recommended to replace getmem and freemem, for example:

var
p: Pointer;
begin
p := GetMemory(256);
GetWindowText(Handle, p, 256);
ShowMessage(PChar(p)); {Form1}
FreeMemory(p);
end;

Summary:
New is to allocate memory to pointers of known sizes;
Getmem mainly allocates memory to non-type pointers;
Use getmemory instead of getmem.

What is the difference between allocmem and allocmem?

Allocmem will be initialized at the same time after memory allocation (empty), and getmem will not. First, verify the following:

VaR
P1, p2: pointer;
Begin
P1: = allocmem (256 );
Showmessage (pchar (P1); {null is displayed here}
Freememory (P1 );

P2: = getmemory (256 );
Showmessage (pchar (P2); {some junk data is displayed here, the content depends on the content of the address before allocation}
Freememory (P2 );
End;

Differences between freememory and freemem:
1. freememory checks whether it is nil and then freemem. This is a bit similar: free and destroy;
2. freemem also has a default parameter that specifies the size of the memory to be released. If this parameter is not specified, all resources will be released (you do not need to release only a part of the memory );
3. The dispose corresponding to new can also be replaced by freemem or freememory.

Use freemory whenever possible to release the memory allocated by getmem, getmemory, allocmem, reallocmem, and reallocmemory.

Reallocmem and reallocmemory are re-allocated based on the allocated memory. The two reallocmemory and reallocmem have more nil judgment than reallocmem. Use reallocmemory whenever possible. For example:

type
TArr = array[0..MaxListSize] of Char;
PArr = ^TArr;
var
arr: PArr;
i: Integer;
begin
arr := GetMemory(5);
for i := 0 to 4 do arr[i] := Chr(65+i);
ShowMessage(PChar(arr)); {ABCDE}

arr := ReallocMemory(arr, 26);
ShowMessage(PChar(arr)); {ABCDE}
for i := 0 to 25 do arr[i] := Chr(65+i);
ShowMessage(PChar(arr)); {ABCDEFGHIJKLMNOPQRSTUVWXYZ}
end;

Note that in the preceding example, the Tarr type is defined as an array that is large enough. This array sets aside sufficient possibilities, but is generally not used in all cases.
We generally only use the pointer to this array, otherwise the memory will be insufficient during initialization.
Even if its pointer is used, the new row cannot be used for initialization. The getmem, getmemory, allocmem, reallocmem, and reallocmemory values should be used to apply for initialization.
It should be noted that the re-allocation of memory may also result in a smaller score. The larger the score, the larger the score should ensure the existence of the previous data.
This concept is used in the tlist class in VCL.

If you cannot accept such a large array in your mind (in fact, it's okay, a pointer is too big? We only use its pointer), you can also do this:

type
TArr = array[0..0] of Char;
PArr = ^TArr;
var
arr: PArr;
i: Integer;
begin
arr := GetMemory(5);
for i := 0 to 4 do arr[i] := Chr(65+i);
ShowMessage(PChar(arr)); {ABCDE}

arr := ReallocMemory(arr, 26);
ShowMessage(PChar(arr)); {ABCDE}
for i := 0 to 25 do arr[i] := Chr(65+i);
ShowMessage(PChar(arr)); {ABCDEFGHIJKLMNOPQRSTUVWXYZ}
end;

This seems confusing. What can an array with only one element do?
It should be understood as follows: This element is enough to indicate the starting point of data and the size and regularity of data elements.

In addition, the four functions sysgetmem, sysfreemem, sysallocmem, and sysreallocmem should be the underlying implementation of these functions. We should not directly use them when using the default Memory Manager of Delphi.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.