To avoid memory leaks, you must call FreeCallInfo to free the values stored in the PBCallInfo structure after using the structure. However, after making a function call, you might want to save the return value or a by reference argument value into a local variable you can use later.
There are techniques for saving values so they are still available after the call to FreeCallInfo. How you save your result into a local variable depends on whether you want to save a simple value, a pointer value, or an object value.
Saving simple values
Saving simple values is straightforward. When you call one of the IPB_Value Get<type> methods for a simple value, such as GetInt or GetReal, the actual data is returned. As a result, you can simply save the values of any of the following datatypes:
pbvalue_byte
pbvalue_int
pbvalue_uint
pbvalue_long
pbvalue_ulong
pbvalue_real
pbvalue_double
pbvalue_longlong
pbvalue_boolean
pbvalue_char
Saving pointer values
A pointer value does not contain data. It contains a pointer to a memory location where the data is stored. When you call one of the IPB_Value Get<type> methods for a pointer value, such as GetBlob or GetTime, it returns a pointer to memory that is also pointed to by IPB_Value.
When you call FreeCallInfo, the memory to which IPB_Value points is released and the data is deleted. Because this is the same data pointed to by the pointer returned by the Get<type> method, that pointer can no longer be used to represent the data.
This applies to the following pointer value datatypes, as well as to the pbarray datatype:
pbvalue_dec
pbvalue_string
pbvalue_blob
pbvalue_date
pbvalue_time
pbvalue_datetime
If you want to save the data in a pointer value, you can use the AcquireValue, AcquireArrayItemValue, and ReleaseValue methods to acquire and release the data.These methods clone a new IPB_Value that is not freed until you call ReleaseValue and reset the existing IPB_Value pointer.
Can be used for other datatypes
You can use AcquireValue and AcquireArrayItemValue to acquire values of any datatype.
Like the Get<type> methods, AcquireValue and AcquireArrayItemValue return a pointer to the memory where the data is stored, but they also reset the IPB_Value pointer so that IPB_Value no longer points to the actual data. When you call FreeCallInfo, the data pointed to by the value acquired using AcquireValue and AcquireArrayItemValue is unaffected.
The original value is reset to zero or null, so it can no longer be used. Attempts to get or acquire the original value return zero or null until another IPB_Value is set to the value.
If the IPB_Value acquired using AcquireValue is an array, the entire array is acquired. To acquire only an element of the array, use AcquireArrayItemValue. When you have finished using the data, you must free the memory using the ReleaseValue method.
The processing that the AcquireArrayItemValue and ReleaseValue methods perform results in poor performance when handling large arrays. It is more efficient to get the type of the array and handle each type with appropriate type-specific functions.
Caution
You must call the ReleaseValue method to free the data. If you do not do so, a memory leak will occur. You must not call ReleaseValue to release a pointer that was not acquired using AcquireValue and AcquireArrayItemValue. Doing so might cause the PBVM to crash.
Saving object values
Strictly speaking, object values are also pointer values, but the PBVM handles them differently. You use the IPB_Session AddLocalRef and AddGlobalRef methods to add a reference to the object. If there is a reference to an object, it is not deleted when FreeCallInfo is called.
When you no longer need the object, call RemoveLocalRef or RemoveGlobalRef to decrease the reference count for the object. If the reference count is decreased to zero, the object is deleted automatically.
There is an important difference between AddLocalRef and AddGlobalRef. A reference added by AddLocalRef can be deleted automatically when the local frame is popped up. The local frame can be popped by calling PopLocalFrame or when the current function returns. However, a reference added by AddGlobalRef is deleted only when RemoveGlobalRef is called or the session ends.
You must use these methods in pairs; that is, use RemoveLocalRef to remove references created with AddLocalRef, and use RemoveGlobalRef to remove references created with AddGlobalRef.