vendredi 14 janvier 2022

emulate new and delete with placement new for alignment

Below code allocates aligned memory. However, static checkers are rightly complaining about new and not matching with delete but rather with free in below case. To fix the static checkers complain I removed CURRENTLY_WORKING_CODE macro below. But that is causing crash and I know the reason why. Is there any way to get rid of static checkers warnings?

Please don't suggest any other way of allocating aligned memory. I looked into this post but couldn't figure out best way to use that.

If it is really required than I am ready to also go with a specific compiler.

#include <assert.h>
#include <iostream>
#include <cstdlib>
#include <stdint.h>
#include <cstring>
 
#define CURRENTLY_WORKING_CODE 

void* operator new  (size_t n);
void* operator new[](size_t n);
void* operator new  (size_t n, int alignment);
void* operator new[](size_t n, int alignment);
 
template <typename T>
T* aligned_malloc(size_t n, int alignment) {
    return new (alignment) T[(size_t)n];
}
 
template <typename T>
void aligned_free(T *p, int x) {
    for (size_t i = 0; i < x; i++) {
        p[i].~T();
    }
    free(p);
}
 
void* malloc_aligned(size_t n, int alignment) {
    void* mem = nullptr;
    if (posix_memalign(&mem, static_cast<size_t>(alignment), n)) {
        printf("Fatal : couldn't allocate %zd bytes\n", n);
        exit(1);
    }
    return mem;
}
 
void* operator new(size_t n) {
    return malloc_aligned(n, 16);
}
 
void* __attribute__((weak)) operator new(size_t n, int alignment) {
    return malloc_aligned(n, alignment);
}
 
void* operator new[](size_t n) {
    return malloc_aligned(n, 16);
}
 
void* operator new[](size_t n, int alignment) {
    return malloc_aligned(n, alignment);
}
 
//not shown entire code
template <typename T>
class AlignedArray {
    public:
        AlignedArray():m_vElem(0),m_nElem(0),m_owner(true) {  }
        AlignedArray(int nElem):m_vElem(0), m_owner(true) { alloc(nElem); }
        AlignedArray(int nElem, int alignment):m_vElem(0), m_owner(true) { alloc(nElem, alignment); }
 
        ~AlignedArray() { 
            if(m_owner && m_vElem) {
                AlignedArray::free();
            } 
        }
 
        void alloc(int nElem, int alignment = 8) {
            m_nElem = nElem;
#ifdef CURRENTLY_WORKING_CODE
            m_vElem = new (alignment) T[(size_t)nElem];
#else
            m_vElem = aligned_malloc<T>(nElem, alignment);
#endif
        }
 
        void free() {
#idef CURRENTLY_WORKING_CODE
            delete []m_vElem;
#else
            aligned_free(m_vElem, m_nElem);
#endif
            m_vElem = nullptr;
            m_nElem = 0;
        }
 
    protected:
        T*   m_vElem;
        int  m_nElem;
        bool m_owner;
};
 
typedef struct def {
    int x;
    AlignedArray<int> xyz;
} def;
 
typedef struct abc {
    int x;
    AlignedArray<def> xyz;
} abc;
 
int main() {
    AlignedArray<abc> x(1);
}

Aucun commentaire:

Enregistrer un commentaire