[CareerCup] 13.9 Aligned Malloc and Free Function 寫一對申請和釋放記憶體函式

Grandyang發表於2015-11-03

 

13.9 Write an aligned malloc and free function that supports allocating memory such that the memory address returned is divisible by a specific power of two.
 EXAMPLE
 align_malloc (1000,128) will return a memory address that is a multiple of 128 and that points to memory of size 1000 bytes.
 aligned_free() will free memory allocated by align_malloc

 

這道題讓我們寫一對申請和釋放記憶體的函式,而且要求我們申請的記憶體塊的起始地址要能夠被2的倍數整除。題目中給了例子,讓我們申請1000位元組大小的記憶體空間,且起始地址要能被128整除。我們知道,在使用malloc申請記憶體時,我們無法控制堆中具體哪塊記憶體被申請了,如果我們非要首地址被128整除,那麼我們需要些小技巧:我們需要再申請127個位元組大小,這樣我們的首地址即時申請到的不能被128整除,我們也能夠調整到能整除的位置,並且後面的記憶體空間也足夠1000位元組,可以使用如下的程式碼來申請:

void* aligned_malloc(size_t required_bytes, size_t alignment) {
    int offset = alignment - 1;
    void *p = (void*)malloc(required_bytes + offset);
    void *q = (void*)(((size_t)(p1) + offset) & ~(alignment - 1));
    return q;
}

我們申請了額外的空間alignment-1,然後再調整首地址的位置通過和~(alignment-1)相與,得到能被alignment整除的地址,下面我們就要來看如何釋放記憶體,由於我們多申請了offset的記憶體,我們最終也需要將這些記憶體釋放掉,我們需要一個指標來記錄整個記憶體塊的起始位置,由於新加了指標,別忘了還要給指標申請空間,所以我們需要多申請的空間大小為alignment - 1 + sizeof(void*),參見如下程式碼:

 

class Solution {
public:
    void* aligned_malloc(size_t required_bytes, size_t alignment) {
        void *p1;
        void **p2;
        int offset = alignment - 1 + sizeof(void*);
        if ((p1 = (void*)malloc(required_bytes + offset)) == NULL) {
            return NULL;
        }
        p2 = (void**)(((size_t)(p1) + offset) & ~(alignment - 1));
        p2[-1] = p1;
        return p2;
    }
    void aligned_free(void *p2) {
        void *p1 = ((void**)p2)[-1];
        free(p1);
    }
};

我們定義一個雙指標p2,在-1的位置存上p1,也就是整個申請的記憶體塊的起始地址,在0的位置存上能被alignment整除的位置,釋放記憶體時從p2中提取出p1,將p1釋放掉即可。

相關文章