Memory allocation

Many of the CARMA API functions require that either the RAM or the CARMA client allocate memory to store function results or parameters that are passed between the RAM and the CARMA client. For all functions other than extractMember and putMember, a one dimensional array will need to be allocated by the RAM and freed by the client to store sets of instance information, member information, and other information. The following diagram illustrates how the RAM should allocate this array:

Figure 1. Simple one dimensional array as would be allocated by a RAM

Each element in the array depicted above is of data structure type type. typePtr is a type pointer (of type type*) that serves as a handle to the newly allocated memory. In C, this memory can be allocated with the following code:

typePtr = (type*) malloc(sizeof(type) * numElements);

where numElements is the number of array indices that need to be created. The memory typePtr points to must be freed by the client once it is no longer needed.

The putMember and extractMember functions use two-dimensional arrays to transfer member contents, with each array row containing one of the member's records. For extractMember, the RAM should allocate the array and the CARMA client should free the array. For putMember, the CARMA client should both allocate and free the array. In both cases, the array should be allocated as illustrated in the following diagram:

Figure 2. Two-dimensional character array as used in extractMember and putMember

charPtrPtr is a pointer to a char pointer (it is of type char**) that serves as a handle to an array of char pointers (elements of type char*). The data for the two-dimensional character array is actually stored in a one-dimensional character array; the idea of rows and columns is purely conceptual. The array of char pointers is used to provide handles to the first element in each row of the "two-dimensional" array. Thus, in the illustration, the first row of the two-dimensional array consists of elements 0a and 0b, with 0a being the first element of that row; the second row consists of elements 1a and 1b, with 1a being the first element of that row; and so on.

To allocate a two-dimensional array such as the ones required for the extractMember and putMember functions, the CARMA client must first create charPtrPtr. In C, use the following declaration:

char** charPtrPtr;

If the CARMA client is allocating the two-dimensional character array (as is the case for the putMember function) the array can now be allocated. In C, the CARMA client should use the following code:

charPtrPtr = (char**) malloc(sizeof(char*) * numRows);
*charPtrPtr = (char*) malloc(sizeof(char) * numColumns * numRows);
for(i = 0; i < numRows; i++)
   (charPtrPtr)[i] = ( (*charPtrPtr) + (i * numColumns) );

where numRows is the number of rows and numColumns is the number of columns in the two-dimensional array. The first line allocates the array of char pointers (one pointer for each row in the two-dimensional array), the second line allocates the array that holds the data for the two-dimensional array, and the for loop assigns each of the char pointers in the char pointer array to a row in the two-dimensional array.

If the RAM is allocating the two-dimensional character array (as is the case for the extractMember function) an extra step is required before the array can be allocated: charPtrPtr needs to be passed by reference to the RAM as extractMember's contents parameter; that is, a pointer to charPtrPtr needs to be passed. This is necessary so that the client has a handle to the two-dimensional array after the RAM has allocated the array. Suppose that the RAM receives a parameter named contents of type char*** in the RAM function that will allocate the two-dimensional array. The RAM should then allocate the two-dimensional array, using contents as a handle to the array. In C, the RAM should use the following code to allocate the two-dimensional array:

*contents = (char**) malloc(sizeof(char*) * numRows);
**contents = (char*) malloc(sizeof(char) * numColumns * numRows);
for(i = 0; i < numRows; i++)
   (*contents)[i] = ( (**contents) + (i * numColumns) );

where numRows is the number of rows and numColumns is the number of columns in the two-dimensional array. The first line allocates the array of char pointers (one pointer for each row in the two-dimensional array), the second line allocates the array that holds the data for the two-dimensional array, and the for loop assigns each of the char pointers in the char pointer array to a row in the two-dimensional array.

Regardless of who allocated the array, the CARMA client must free the two-dimensional character array in both the extractMember and putMember functions. In C, the CARMA client should use code similar to the following:

free(charPtrPtr[0]);
free(charPtrPtr);

This frees the data array before freeing the char pointer array, thus avoiding a memory leak.