在C++中实现aligned_malloc的方法

 更新时间:2021年03月09日 08:24:09   作者:老胡写代码  
这篇文章主要介绍了在C++中实现aligned_malloc的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

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以上,那么还是推荐使用系统自带的方法。

到此这篇关于在C++中实现aligned_malloc的文章就介绍到这了,更多相关C++实现aligned_malloc内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解c++中的异常

    详解c++中的异常

    程序在运行过程中,有对也就有错,正确那么就不用说了,但是如果错误,那么我们如何快速的定位到错误的位置,以及知道发生了什么错误。当一个函数发现自己无法处理的异常,就会抛出一个异常,让函数调用者直接或者间接的处理这个错误。本文将详解介绍c++中的异常
    2021-06-06
  • C++中opencv4.1.0环境配置的详细过程

    C++中opencv4.1.0环境配置的详细过程

    这篇文章主要介绍了C++中opencv4.1.0环境配置的详细过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • C语言实现逆序输出详细

    C语言实现逆序输出详细

    这篇文章主要介绍了C语言实现逆序输出。主要实现C语言实现对数组元素依次赋值然后按照逆序输出,下面文章小编将详细解说,需要的朋友可以参考一下
    2021-10-10
  • Clion下载安装使用的详细教程(Win+MinGW)

    Clion下载安装使用的详细教程(Win+MinGW)

    这篇文章主要介绍了Clion下载安装使用教程(Win+MinGW),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • C++中rapidjson将map转为json的方法

    C++中rapidjson将map转为json的方法

    今天小编就为大家分享一篇关于C++中rapidjson将map转为json的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • 数据结构 数组顺序存储详细介绍

    数据结构 数组顺序存储详细介绍

    这篇文章主要介绍了数据结构 数组顺序存储详细介绍的相关资料,需要的朋友可以参考下
    2017-05-05
  • 关于C++中由于字节对齐引起内存问题定位分析

    关于C++中由于字节对齐引起内存问题定位分析

    前几天遇到一个稀奇古怪的问题,在创建对象的时候程序异常退出,查找代码发现结构体数组问题,最终把问题简化得到解决方法,下面小编把我的问题及解决方案分享到脚本之家平台供大家参考下
    2021-06-06
  • C语言实现学生信息管理程序

    C语言实现学生信息管理程序

    这篇文章主要为大家详细介绍了C语言实现学生信息管理程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • VSCode配置C语言环境的方法

    VSCode配置C语言环境的方法

    这篇文章主要介绍了VSCode配置C语言环境的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • C语言贪吃蛇经典小游戏

    C语言贪吃蛇经典小游戏

    这篇文章主要为大家详细介绍了C语言贪吃蛇经典小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01

最新评论