Search code examples
c++performanceoptimizationalignment

Aligning memory when allocating on heap


I came across this example implementation of the new() operator in C++:

void *operator new(size_t size){
    if(void *mem = malloc(size)){
        cout << "allocated memory" << endl;
        return mem;
    }
    else{
        throw bad_alloc();
    }
}

How would one edit this function so that memory could be allocated on particular "byte boundaries" (I am referring to data alignment discussed in performance circles)?

(I am assuming this is not just done automatically by the compiler- or if it is, are there any advantages to implementing it manually?)


Solution

  • You will need to find a way to retain the original pointer, otherwise your free will go horribly bad.

    Aligning is a simple case of (assuming that alignment is a 2n value):

     void *aligned = reinterpret_cast<void *>(
            (reinterpret_cast<uintptr_t>(mem) + alignment-1) & ~(alignment-1));
    

    However, like I said, you will need to save the original pointer somewhere. This probably means allocating "a bit extrra" (e.g sizeof(void *)).

    So we end up with something like this:

     assert(!(alignment & alignment-1)); // Don't like aligment not power of 2.
    
     size_t extra = sizeof(void *);
     void *mem = malloc(size + extra + alignment-1); 
     if (!mem) 
        throw bad_alloc();
    
     void *aligned = reinterpret_cast<void *>(
            (reinterpret_cast<uintptr_t>(mem) + extra + alignment-1) & ~(alignment-1));
     void **ptr = reinterpret_cast<void **>(aligned); 
     ptr[-1] = mem;
     return aligned; 
    

    Then in the operator delete, you need to dig out your original pointer:

     operator delete(void *mem)
     {
        void **ptr = reinterpret_cast<void **>(mem); // This is the "aligned" pointer. 
        void *orig_mem = ptr[-1]; 
        free(orig_mem);
     }