Prior to calling a compiler generated encode function, a variable of the type generated by the compiler must be populated. This is normally a straightforward procedure - just plug in the values to be encoded into the defined fields. However, things get more complicated when more complex, constructed structures are involved. These structures frequently contain pointer types which means memory management issues must be dealt with.
There are two alternatives for managing memory for these types:
Allocate the variables on the stack and plug the address of the variables into the pointer fields,
Use the rtxMemAlloc and rtxMemFreePtr run-time library functions or their associated macros.
Allocating the variables on the stack is an easy way to get temporary memory and have it released when it is no longer being used. But one has to be careful when using additional functions to populate these types of variables. A common mistake is the storage of the addresses of automatic variables in the pointer fields of a passed-in structure. An example of this error is as follows (assume A, B, and C are other structured types):
typedef struct { A* a; B* b; C* c; } Parent; void fillParent (Parent* parent) { A aa; B bb; C cc; /* logic to populate aa, bb, and cc */ ... parent->a = &aa; parent->b = &bb; parent->c = &cc; } main () { Parent parent; fillParent (&parent); encodeParent (&parent); /* error: pointers in parent reference memory that is out of scope */ … }
In this example, the automatic variables aa, bb, and cc go out of scope when the fillParent function exits. Yet the parent structure is still holding pointers to the now out of scope variables (this type of error is commonly known as "dangling pointers").
Using dynamic memory for the variables solves this problem. The rtxMemAlloc call can be used to allocate memory for each of the dynamic fields. The rtxMemFree function is used to release all memory held within the context at once. This is typically done after the populated variable is encoded. The rtxMemFreePtr function can be used to free an individual memory element.
It is recommended that these functions be used instead of the standard C memory management functions so that if the underlying memory management scheme is changed (see Dynamic Memory Management above) all memory handling within the application is changed to the new scheme without any recoding being required.