# Binutils Libiberty: `objalloc` ## Introduction There is a small library in libiberty called **objalloc**. It is a memory management tool that an "object" can be used to simplify space allocation. An "object" can be any kind of data structure implementation, for example, a list that the elements are pointers points to dynamically allocated spaces. We will have a little pseudo code example in the following sections. **objalloc** assumes: > ... that the object will want to allocate space as it goes along, but will never want to free any particular block. The source code for the **objalloc** is pretty simple, only about 400 lines of code in the 2 files: * *[include/objalloc.h](https://github.com/bminor/binutils-gdb/blob/master/include/objalloc.h)* * *[libiberty/objalloc.c](https://github.com/bminor/binutils-gdb/blob/master/libiberty/objalloc.c)* ## Example Let's implement a list structure. The list provides only simple interfaces: * Create a list * Append a string to the list * Print the entries of the list * Free the memory allocated in the list When the list is created, all the entires are NULL pointers. To append a new entry, the list allocates a memory and we can first create an `struct objalloc` with `objallo_create()`, and use `objalloc_alloc()` to allocate a memory space for the new entry. When it's time to cleanup memories, we can call `objallo_free()` on the `struct objalloc` we created earlier. The full example code can be found in the Github repo: https://github.com/hauhsu/libiberty-objalloc-example ### Defining `struct list` The struct defines a list of strings (`chat *`) pointers, the size of the list, the last used index and the memory space to store the contents: ```c struct list { char **entry; int size; int last_index; struct objalloc *memory; }; ``` Note that the `memory` field is managed by an `objalloc`, and the `**entry` is an string array that will point to the memories allocated by the `objalloc`. ### Creating a list The function to create a list looks like: ``` c struct list* list_create(int size) { struct list *ret = malloc(sizeof(struct list)); if (ret == NULL) return NULL; ret->size = size; ret->last_index = -1; ret->memory = objalloc_create(); /* Use objallo for memory management. */ ret->entry = objalloc_alloc(ret->memory, sizeof(void*) * size); return ret; } ``` As you can see, we created an `objalloc` with `objallo_create()` and use it to allocate memory for our `entry`. ### Appending a string to a list To append a string to a list, we need to check whether the list is alyready full: ``` c bool list_append(struct list *l, const char* str) { if (l->last_index == l->size-1) return false; ... } ``` If there are still spaces, use `objalloc_alloc()` to acquire a space for the string, and use `memcpy` to copy the characters into the newly allocated memory: ```c ... l->last_index ++; l->entry[l->last_index] = objalloc_alloc(l->memory, strlen(str)); strcpy(l->entry[l->last_index], str); return true; } ``` ### Freeing a list This is the whole point of using `objalloc`. With `objallo`, we don't have to iterate over the entry, but using `objalloc_free` to free the `memory` field. `objalloc` will handle the dirty work for us: ``` void list_free(struct list *l) { objalloc_free(l->memory); free(l->entry); free(l); } ``` ## Build and run Here are the simple commands to build and run the example: ``` $ gcc *.c -o list $ ./list list[0] = hello list[1] = world ```