Accessing auxiliary data

Special purpose custom memory allocation facilities can store additional data with the allocated memory. This data might include allocation time statistics or pointers to clean up functions to be called when the memory is freed. Often this is accomplished by allocating a few extra bytes of memory at the start of each block to store these values, and returning a pointer to the memory past these values.

Purify allows you to associate user data with every allocated block of memory by using the functions purify_set_user_data and purify_get_user_data.

Auxiliary data example

Extending the pool allocator example, assume that the function AllocateFromPool stores the pool-id and the block size with each block allocated. Without Purify, you might use the two words immediately preceding the block returned to the user for these values.

char* AllocateFromPool(int pool_id, int size) {
     char *mem = ... get size+8 bytes ..
     /* Store the pool_id and size. */
      *((int*)mem + 0) = pool_id;
      *((int*)mem + 1) = size;
     /* Return the rest of the chunk to the user */
     return (char*)((int*)mem + 2);
}
    
int BlockSize(char* mem) {
     return *((int*)mem - 1);
    
}

With Purify, you can implement this by using:

#ifdef PURIFY
char* AllocateFromPool(int pool_id, int size) {
    char *mem = malloc(size);
    purify_set_pool_id(mem, pool_id);
    purify_set_user_data(mem, size);
    return mem;
}
    
int BlockSize(char* mem) {
    return purify_get_user_data(mem);
}
#endif /* PURIFY */


You can also use the user data field to associate a string name to the memory for debugging purposes:

char* Malloc(int size, char* debug_name)
    char* mem = malloc(size);
    purify_set_pool_id(mem, 0);
    purify_set_user_data(mem, debug_name);
    return mem;
}
    
void PrintBlock(char* mem) {
    char* debug_name = purify_get_user_data(mem);
    printf("%s\n", debug_name);
    purify_describe(mem);
}

Notes: