我正在使用C ++编写aligned_malloc
实现,主要使用以下代码,可以在Interwebs的各个地方找到,包括SO:
void * aligned_malloc(size_t size, int align) {
if (align < 0) {
return NULL;
}
void *ptr;
void *p = malloc(size + align - 1 + sizeof(void*));
if (p != NULL) {
ptr = (void*) (((ptrdiff_t)p + sizeof(void*) + align -1) & ~(align-1));
*((void**)((ptrdiff_t)ptr - sizeof(void*))) = p;
return ptr;
}
return NULL;
}
void aligned_free(void *p) {
void *ptr = *((void**)((ptrdiff_t)p - sizeof(void*)));
free(ptr);
return;
}
我在*(void**)
中获得aligned_malloc
。我的误解是aligned_free
中的演员。由于我们只是想要价值并且不必分配给它,为什么不使用
void *ptr = ((void*)((ptrdiff_t)p - sizeof(void*)));
而不是
void *ptr = *((void**)((ptrdiff_t)p - sizeof(void*)));
我认为它是一样的,但是当我尝试第一个对齐为64时,它给了我一个错误,但是当我尝试第二次演员时,程序正常工作。那两者有什么区别?为了便于阅读,我省略了适当的C ++演员表。
答案 0 :(得分:5)
让我们简化代码:
int x = 7;
void * p = &x;
void * q = &p;
现在让我们绘制一个图表:
+---+
x | 7 |
+---+
^
|
+-|-+
p | * |
+---+
^
|
+-|-+
q | * |
+---+
您是否看到p
和q
不相等?如果您有q
,并且想要转到p
,则必须取消引用q
。但由于void*
无法解除引用,您必须向类型系统承诺它将在取消引用后找到另一个指针,因此在取消引用之前转换为void**
。
assert(q != p);
assert(*(void**)q == p);
答案 1 :(得分:1)
如果你更换
,应该更清楚void *ptr = *((void**)((ptrdiff_t)p - sizeof(void*)));
与等效
void *ptr = ((void**)((ptrdiff_t)p - sizeof(void*))) [0];
*不是任何强制转换的一部分,它取消引用指针。它正在从内存中读取数据。
另一方面,您应该获得一本关于C ++的非常好的书,并查看C ++库中内置的函数。这更有可能没有问题。使用malloc_aligned意味着你有两类指针,malloc分配的指针和malloc_aligned分配的指针,两者都是不兼容的。