B4R Tutorial Memory, Variables and Objects

Memory is a big issue in Arduino.

1. The available RAM is very small compared to other platforms. For example the Uno has 2k of RAM.
2. There is no sophisticated heap management which means that usage of dynamic memory should be avoided.
3. Programs are expected to run for a long time with zero memory leaks.

There are two types of variables in B4R: local variables and global variables.

Local variables are always created on the stack. This means that any object created in a sub, other than Process_Globals, will be destroyed when the sub ends (this is not the case in other B4X tools).

Global objects, which are objects created in Process_Globals, are not stored in the stack and will always be available.
Note that global variables, except of primitives, behave as constants. You cannot redim them and they cannot be reassigned.

Consider this code:
B4X:
Sub MySub As Pin
Dim p As Pin
Return p
End Sub
The compiler will throw the following error:
"Objects cannot be returned from subs (only primitives, strings and arrays of primitives are allowed)".
The reason for this error is that the Pin object created in the sub is destroyed when MySub ends.
Primitives (numeric types and boolean) are not problematic as the actual value is passed.
B4R does allow returning strings and arrays of primitives. It involves copying those objects in the stack.

As a general rule, objects should be declared as process globals.

Stack Buffer

B4R maintains an additional "stack" named stack buffer. This buffer is used internally when a method needs to allocate memory. Remember that the heap is never used.

For example the NumberFormat keyword accepts a number and returns a formatted string. The string must be allocated somewhere. It is allocated on the stack buffer. Like all other objects it will be destroyed when the sub ends.
The buffer is also used when the array size is not known during compilation.

The default size of the stack buffer is 300 bytes. This can be changed with the #StackBufferSize attribute.
If you encounter memory issues then check the value of StackBufferUsage keyword (in the relevant sub).

ByteConverter

ByteConverter type from rRandomAccessFile includes methods to convert objects and other types to bytes and vice versa. It also allows copying objects with the ObjectCopy method. This method can be used to copy a local object to a global variable.

Notes

- Only single dimension arrays are supported.
- Local variables are not set to zero automatically.

You can set the value in the declaration:
B4X:
Dim counter As Int = 0

- You can use the GlobalStore module to copy local objects to a global memory storage: https://www.b4x.com/android/forum/t...ore-global-objects-storage.73863/#post-469000
 
Last edited:

Beja

Expert
Licensed User
Longtime User
B4X:
Dim i(10) As Int
i(10) = 100 'bad things can happen as the index of the last element is 9

does that mean Dim i(10) As Int is equivalent to Dim i(0 to 9) as int, so I shouldn't assign anything to i(10)?
 

XbNnX_507

Active Member
Licensed User
Longtime User
B4X:
Sub MySub As Pin
Dim p As Pin
Return p
End Sub
p is never returned in B4R. yet in B4J and B4A it does return p.
how do we know when p is destroyed in B4J or B4A ?
 

johndb

Active Member
Licensed User
Longtime User
B4X:
Sub MySub As Pin
Dim p As Pin
Return p
End Sub
p is never returned in B4R. yet in B4J and B4A it does return p.
how do we know when p is destroyed in B4J or B4A ?
I think that in B4A and B4J the object is only destroyed when there are no references to the object and when the object is destroyed during memory housekeeping. I hope someone corrects me if this incorrect but I find it very annoying when B4A and B4J uses this technique. I find it much more predictable when local objects in subroutines are destroyed upon subroutine completion or when a class that references the object is destroyed.

John
 
Top