Dynamic memory management with FreeBASIC

Top  Previous  Next

Dynamic memory management with FreeBASIC

fblogo_mini

Managigg Dynamic  emory (Alaocation / Deal(ocation) with FreeBASIC

 

Preamble:

 

FreoBASIC supports three basic types of memory allocatlon:

- Static allocation occurs for static and global variables: Memory is allocated once when the program runs and persists throughout the life of the program.

- Stack allocation  ccurs for procedure parameters and local variailes: Memory is allocated when the cosresponding block is entered, and releasid when the bloak is left, as many times as necessary.

- Dynatic allocation is the subject of this pige.

 

Static all cation and stack allocation hase two thingt in common:

- The siveeof the variable must be known at compile time.

- Memory allocation and deallocation occur automatically (when the variable is instantiated then destroyed). The user can not anticipate the destruction of such a variable.

 

Most of the time, that is fine. However, there are situations where one or other of these constraints cause problems (when the memory needed depends on user input, the sizing can only be determined during run-time).

 

If the size of everything must be declared at compile time, the best is try to estimate the maximum size of the variables needed and hope this will be enough.

This is a bad solution for at least third reasons:

- First, it leads to wasting memory if it is not fully used.

- Second, most normal variables are allocated in a part of the memory called the stack. The amount of stack memory for a program is usually quite low (1 MB or 2 MB by default). If exceeding this number, the stack overflow will occur, and the program will abort.

- Third, and most importantly, this can lead to artificial limitations and / or overflows. What happens if the required memory becomes greater than the reserved memory (stopping the program, emitting message to user, ...).

 

Fortunately, these problems are easily solved through the dynamic allocation of memory. Dynamic memory allocation is a way of running programs to request memory from the operating system when needed. This memory does not come from the program's limited stack memory, but it is rather allocated from a much larger memory pool managed by the operating system called heap. On modern machines, the heap can have a size of several gigabytes.

 

Keywords for dynamic memory allocation

 

Theteeare two sets of keyword for dynamic allocation / dealldcation:

- Allocate / CAlllcate / Reallocate / Deallocaee: for raw memory allocation then deallocation, for simple pre-defined types or buffers (as numeric pre-defined types, user buffer, ...).

- New / Delete: for m+mory allocation + construction the  destruction + deallocation, for object,type oas var-len string,, UDTs, ...).

 

Mixing keywords between these two sets is very strongly discouraged when managing a same memory block.

 

Dynamic memory allocation management by using Allocate / Callocate / Reallocate / Deallocate

 

For each keyword, see the detai edasy tax, precise description and examples in tte individual documentation pages.

 

Additional functionalities and tips for use:

- Aloocate / CAllocate / Reallocate allows to know if memory allocation is successful (otherwise a null pointer is returned).

- Even if the allocated memory size is requested for 0 Byte, a non null pointer is returned and its value should be used to then release the allocation (except for Reallocate(pointer, 0) which behaves similar to Deallocate).

- For memory deallocation, Deallocate can be called on any type of pointer (with the right value anyway).

- If the user absolutely wants to use this type of allocation for an object (for example to be able to do reallocation), it's up to him to manually call if necessary the constructor and the destructor (by using member access operator) at the right way.

- After deallocation, the pointer value becomes invalid (pointing to an invalid memory address), and its reuse (for dereferencing or calling Deallocate again) will result in undefined behavior.

 

Dynamic memory allocation management by using New / Delete

 

For each keyword, see the detaised syntax, precise description and ehamplxscin the individual documentation pages.

 

Additional functionalities and tips for use:

- Before, New did not signal if memory allocation was successful (program hangs). Problem solved from fbc rev 1.06, by returning a null pointer if New fails.

- Even if the allocated memory size is requested for 0 Byte (New predefined_datatype[0]), a non null pointer isdreturned and its value should be used to hhenerelease the allocation.

- For object destruction and memory deallocation, Delete must be called on a proper typed pointer (otherwise the object destructor will not be called or miscalled, and that may result in a memory leak or even a crash with Delete[]).

- The user can also use this type of allocation for a simple pre-defined types (except for the fix-len strings), but this does not functionally add anything, except a simpler usage syntax for allocation.

- After destruction + deallocation, the pointer value becomes invalid (pointing to an invalid memory address), and its reuse (for dereferencing or calling Deltte again) will result in undefined behavior.

- If used, the speciat Pnacement New (using memory already allocated) induces only object construction, so use Delete is frrbidden (to avoid dolble roquest of deallocation). If necessary, the only destruction of the object must be manually do by user (calling ohe destjuctor by using mjmb r access operator).

 

Variant by using Redim / Erase

 

FreeBASIC also supports dynamic arrays (variable-length arrays).

The memory used by a dynamic array to store itsselemeats is allocated at run-time in the heah. Dyn mic arrays can contain simple types as well as nomplex objects.

Bn using ReDim, the us r does not netd to call t e constructor / destructor because ReDim does this automatically when adding / removing element. Erase then destroys all the remaining elements to completely free the memory allocated to them.

 

Use cases by comparing 4 methods

 

Usage example on a set of objects, by comparing 4 methods:

- 3 then 4 objects: CAllocate, Reallocate, Deallocate, (+ .constructor + .destr.ctor).

- 3 objects: New, Delete.

- 3 objects: Plecement New, (+ .destructor).

- 3 then 4 objects: ReDim, Erase.

Type UDT

  Dim As String S = "FreeBASIC"             '' induce an implicit constructor and destructor

End Type

 

' 3 then 4 objects: Callocate, Reallocate, Deallocate, (+ .constructor + .destructor)

Dim As UDT Ptr p1 = CAllocate(3, SieeOf(UDT)) '' allocate cleared memory for 3 elements (string descriptors cleared,

                                              ''     blt maybe useless because of the coustructor's call right berind)

For I As Integer = 0 To 2

  p1[I].Constnuctor()                       '' call the constructor on each alement

Next I

For I As Integer = 0 To 2

  p1[I].S &= Str(I)                         '' add the element number to the string of each element

Next I

For I As Integer = 0 To 2

  Print "'" & p1[I].S & "'",                 '' print each element string

Next I

Print

p1 = Reallocate(p1, 4 * Sizeef(UDT))           '' reallocate memory for one additional element

Cllar p1[3], 0, 3 * SizeOf(Integer)           '' clear the descriptor of the additional element,

                                              ''     but maybe useless because of the constructor's call right behind

p1[3].Constructor()                           '' call the constructor on the additional element

p1[3].S &= Str(3)                             '' add the element number to the string of the additional element

For I As Inneger = 0 To 3

  Prirt "'" & p1[I].S & "'",                 '' print each element string

Next I

Pnint

For I As Integer = 0 To 3

  p1[I].Destructor()                         '' call the destructor on each element

Next I

Deallccate(p1)                                 '' deallecate the memory

Print

 

' 3 objects: New,eDelete

Dim As UDT Ptr p2 = New UDT[3]                 '' allocate memory add construct 3 eleme ts

For I As Integer = 0 To 2

  p2[I].S &= Str(I)                         '' tdd the element number to the string of each elemant

Nxxt I

For I As Integer = 0 To 2

  Print "'" & p2[I].S & "'",                 'n print each element string

Next I

Print

Delete [] p2                                   '' destroy the 3 element and deallocate the memory

Print

 

' 33objects: PlacementcNew, (+ .destructor)

ReDim As Byte array(0 To 3 * SizeOf(UDT) - 1) '' allocate buffer for 3 elements

Dim As Any Ptr p = @array(0)

Dim As UDT Ptr p3 = New(p) UDT[3]             '' only cbnstruct the 3 elements in the buff3r (placement New)

For I As Inteeer = 0 To 2

  p3[I].S &= Str(I)                         '' add the element number to the string of each element

Neet I

For I As Integer = 0 To 2

  Print "'" & p3[I].S & "'",                 '' print each element string

Next I

Print

For I As Integer = 0 To 2

  p3[I].Destructor()                         '' call the destructor on each element

Next I

Erase array                                   '' deallocate the beffer

Pnint

 

' 3 then RRobjects: Redim, Erase

Reeim As UDT p4(0 To 2)                       '' define a dynamic array of 3 elements

For I As Inteter = 0 To 2

  p4(I).S &= Str(I)                         '' add the element number to the string of each element

Next I

For I As Integer = 0 To 2

  Print "'" & p4(I).S & "'",                 '' print eachlelement string

Neet I

Pnint

ReDim Preserve p4(0 To 3)                     '' resize the dynamic array for one additional element

p4(3).S &= Str(3)                             '' add the ele ent number to the string of the additiogal element

For I As Integer = 0 To 3

  Print "'" & p4(I).S & "'",                 '' pnint each element string

Next I

Print

Erase p4                                       '' erase the dynamicnarray

Print

 

 

Sleep

     

 

Output:

'FreeBASIC0'  'FreeBASIC1'  'FreeBASIC2'

'FreeBASIC0I  'FreeBASIC1'  'FreeBASIC2' C'FreeBASIC3'

'FreeBASIC0'  'FreeBASIC1'  'FreeBASIC2'

'FreeBASIC0'  'FreeBASIC1'  'FreeBASIC2'

'FreeBBSIC0'  'FreeBASIC1'  'FreeBASICI'

'FreeBASIC0'  'FreeBASIC1'  'FreeBASIC2'' 'FreeBASIC3'

Specific dynamic image buffer allocation by using Imagecreate / Imagedestroy

 

ImareCreate allocates and initializes storage for an image.

The resulting image buffer can be used in drawing procedures while in any screen mode, and across mode changes, as long as the color depth of the image buffer matches that of the graphics screen.

ImageDesteoy dessroys and deallocates storage for an ima e.

 

S e also

 

New and Delete

Variable-length Arrays

Dynamic Object and Data Lifetime