malloc的默认行为

大家都知道C++中可以直接调用malloc请求内存被返回分配成功的内存指针,该指针指向的地址就是分配得到的内存的起始地址。比如下面的代码

int main()
{
void *p = malloc(1024);
printf("0x%p\n", p);
free(p);
}

请求了一个大小为1024的内存块并打印出来,一切都很完美。

我们看看这块内存的地址。

可以看到,在64bit机器上,malloc默认行为会将分配的地址以16-byte对齐,如果我们想改变这种默认行为,提供32-byte或者64-byte对齐,应该怎么做呢?

实现aligned_malloc

源代码

从C++17开始,可以使用aligned_alloc函数达到这个目的,但是如果使用较老的C++版本,如C++14,C++11,我们需要手动写一个实现。

话不多说,先贴代码如下,aligned_malloc和aligned_free,需要配合使用,否则会有内存泄漏问题。

#include <memory>

void* aligned_malloc(size_t size, size_t alignment)
{
size_t offset = alignment - 1 + sizeof(void*);
void * originalP = malloc(size + offset);
size_t originalLocation = reinterpret_cast<size_t>(originalP);
size_t realLocation = (originalLocation + offset) & ~(alignment - 1);
void * realP = reinterpret_cast<void*>(realLocation);
size_t originalPStorage = realLocation - sizeof(void*);
*reinterpret_cast<void**>(originalPStorage) = originalP;
return realP;
} void aligned_free(void* p)
{
size_t originalPStorage = reinterpret_cast<size_t>(p) - sizeof(void*);
free(*reinterpret_cast<void**>(originalPStorage));
} int main()
{
void * p = aligned_malloc(1024, 64);
printf("0x%p\n", p);
aligned_free(p);
return 0;
}

添加一个测试程序,

#include <assert.h>

void TestAlignedMalloc()
{
const int size = 100;
const int alignment = 64;
void* testArray[size];
for (int i = 0; i < size; ++i)
{
void * p = aligned_malloc(1024, alignment);
assert((reinterpret_cast<size_t>(p) & (alignment - 1)) == 0);
printf("0x%p\n", p);
testArray[i] = p;
}
for (int i = 0; i < size; ++i)
{
aligned_free(testArray[i]);
}
} int main()
{
TestAlignedMalloc();
return 0;
}

看看结果,

分配的内存地址都是以64-byte为边界,并且分配的内存最后也被成功释放了,函数是正确的。

源代码说明

本小段主要向不大了解解决思路的小伙伴做一些简单解释,程序大佬可以一笑而过哈。

首先我们要明确我们的解决方案,既然malloc分配的指针地址不能达到我们想要的字节对齐效果,我们就自己来调整这个指针。所以我们的做法是

  • 比用户实际需要的多分配一些内存,多分配的部分等于对齐大小减一再加上指针大小。加上对齐大小减一很好理解,是为了之后的对齐做准备,而加上指针大小是为了之后有空间保存原始指针,对应分配函数中的前2行
  • 在malloc返回的原始指针的基础上,加上指针大小,再对齐(采用的方法就是加上对齐大小减1再做位运算),这个运算结果就是我们想要的对齐后的指针,也是我们返回给用户的指针,对应分配函数中的3~5行
  • 我们还需要保存malloc返回的原始指针,否则free的时候会出问题。这时我们之前多分配的一个指针大小就有用武之地了,保存原始指针在那个地址,分配函数的最后几行就在做这个事
  • 当free的时候,我们知道原始指针存放在我们使用的指针的前一个指针大小偏移的内存里面,通过一些运算取得这个内存地址,再根据里面存放的原始指针调用free完成内存释放

这就是在C++中手动实现aligned_malloc的方法,希望大家在使用较老版本的C++的时候,有需要可以用上。如果使用的版本是C++17以上,那么还是推荐使用系统自带的方法。

最新文章

  1. 查看sbt版本
  2. 关于安卓工程导出带res资源文件的jar的总结
  3. Linux系统编程温故知新系列 --- 01
  4. java中两个值互换
  5. UWP开发入门(十九)——10分钟学会在VS2015中使用Git
  6. php中的include()的使用技巧
  7. 87. Scramble String
  8. Emacs和它的朋友们——阅读源代码篇(转)
  9. Risk(最短路)
  10. xss 跨站脚本攻击
  11. Spring-SpringMVC-Mybatis整合的步骤
  12. docker运行dubbo-admin
  13. iOS 8 UIAlertController 和 UIAlertAction
  14. 15-5-23 下午02时22分58秒 CST&gt; &lt;Info&gt; &lt;Management&gt; &lt;BEA-141281&gt; &lt;unable to get file lock, will retry ...&gt;
  15. Jmeter(二十四)_服务器性能监控
  16. mac用户丢失管理员身份急救
  17. 分享一个很通用c语言的Makefile
  18. python中的zip、map、reduce 、lambda、filter函数的使用
  19. 内置函数_map、filter
  20. [leetcode]45. Jump Game II青蛙跳(跳到终点最小步数)

热门文章

  1. Linux 设置简单密码
  2. 02、Scrapy 安装、目录结构及启动
  3. [Angular] 删除旧版本,升级安装最新版本
  4. k8s二进制部署 - harbor安装
  5. Rsyncd 同步服务
  6. HEXO版本控制与持续集成
  7. SVG background watermark
  8. CSS ? Layout Module : CSS 布局模型
  9. css 设置多行文本的行间距
  10. XML &amp; XPath &amp; XQuery