【问题标题】:Aligning memory when allocating on heap在堆上分配时对齐内存
【发布时间】:2013-08-10 19:12:30
【问题描述】:

我在 C++ 中遇到了 new() 运算符的这个示例实现:

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

如何编辑这个函数,以便在特定的“字节边界”上分配内存(我指的是性能圈中讨论的数据对齐)?

(我假设这不仅仅是由编译器自动完成的——或者如果是的话,手动实现它有什么好处吗?)

【问题讨论】:

  • 使用posix_memalign 代替malloc?
  • aligned malloc() in GCC?的可能重复
  • 不是重复的,而是this probably answers the question(链接的问题询问特定算法的工作原理,而不是一般的操作方法解决方案)。
  • malloc 的结果将针对任何对象类型进行适当对齐,因此您只需担心有特殊对齐需求,例如对齐缓存或页面边界。

标签: c++ performance optimization alignment


【解决方案1】:

您需要找到一种方法来保留原始指针,否则您的free 将变得非常糟糕。

对齐是一个简单的例子(假设alignment 是一个 2n 值):

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

但是,就像我说的,您需要将原始指针保存在某个地方。这可能意味着分配“一点额外”(例如sizeof(void *))。

所以我们最终会得到这样的结果:

 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; 

然后在操作符delete中,需要挖出你原来的指针:

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

【讨论】:

  • 在对内存地址应用按位和运算时,您缺少对 (alignment-1) 的按位否定。
  • @Oxygene:谢谢,错了一年多一点... ;)
  • 永远不会太晚 ;)
猜你喜欢
  • 2018-04-03
  • 2017-04-15
  • 2011-06-03
  • 1970-01-01
  • 2014-09-02
  • 2021-03-20
  • 2011-06-25
  • 2019-07-02
  • 2013-03-16
相关资源
最近更新 更多