B4R Tutorial Memory, Variables and Objects

Discussion in 'B4R Tutorials' started by Erel, Apr 11, 2016.

  1. Erel

    Erel Administrator Staff Member Licensed User

    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:
    Code:
    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 in the stack buffer. Like all other objects it will be destroyed when the sub ends.
    The buffer is also 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:
    Code:
    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: Dec 6, 2016
  2. Beja

    Beja Expert Licensed User

    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)?
     
    Cableguy likes this.
  3. Erel

    Erel Administrator Staff Member Licensed User

    Yes.
     
  4. XbNnX_507

    XbNnX_507 Member Licensed User

    Code:
    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 ?
     
    uValentin and johndb like this.
  5. johndb

    johndb Active Member Licensed User

    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
     
    XbNnX_507 likes this.
  6. Rrobyy

    Rrobyy Member

    Can we save an array data to a single variable ?
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    I'm not sure that I understand the question. Can you post an example?
     
  8. Rrobyy

    Rrobyy Member

    for example :
    Code:
    Dim data As Byte = Array As Byte(1,2,3,4)
      
    Dim save As Byte
       .
       .
       .
      
    Log(save) '1234
    is it possible ?
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    Yes. However your code will not print 1234. It will print the ascii values of 1, 2, 3, 4. Change it to:
    Code:
    Dim data() As Byte = "1234" 'or data() As Byte = Array As Byte(49, 50, 51, 52)
    Log(data)
     
Loading...