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的更多相关文章

  1. Python开源框架

    info:更多Django信息url:https://www.oschina.net/p/djangodetail: Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC) ...

  2. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  3. Hadoop 中利用 mapreduce 读写 mysql 数据

    Hadoop 中利用 mapreduce 读写 mysql 数据   有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...

  4. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  5. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  6. Angular杂谈系列1-如何在Angular2中使用jQuery及其插件

    jQuery,让我们对dom的操作更加便捷.由于其易用性和可扩展性,jQuer也迅速风靡全球,各种插件也是目不暇接. 我相信很多人并不能直接远离jQuery去做前端,因为它太好用了,我们以前做的东西大 ...

  7. 关于CryptoJS中md5加密以及aes加密的随笔

    最近项目中用到了各种加密,其中就包括从没有接触过得aes加密,因此从网上各种查,官方的一种说法: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学 ...

  8. In-Memory:在内存中创建临时表和表变量

    在Disk-Base数据库中,由于临时表和表变量的数据存储在tempdb中,如果系统频繁地创建和更新临时表和表变量,大量的IO操作集中在tempdb中,tempdb很可能成为系统性能的瓶颈.在SQL ...

  9. SQL Server中的高可用性(2)----文件与文件组

        在谈到SQL Server的高可用性之前,我们首先要谈一谈单实例的高可用性.在单实例的高可用性中,不可忽略的就是文件和文件组的高可用性.SQL Server允许在某些文件损坏或离线的情况下,允 ...

随机推荐

  1. 郁闷的出纳员 HYSBZ - 1503

    OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的 工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他 ...

  2. entity framwork修改指定字段

    1.ef修改时指修改指定字段public void ChangePassword(int userId, string password) { var user = new User() { Id = ...

  3. Chapter Zero 0.1.2 CPU的架构

    CPU的架构 CPU内部含有一些微指令, 我们所使用的软件都要经过CPU内部的微指令集达成才行. 这些指令集的设计又分为两种设计理念, 这就是目前世界上常见的两种主要CPU架构: 精简指令集(Redu ...

  4. HashMap三百问

    文章目录: 一.JDK1.7之HashMap 二.JDK1.8之HashMap 三.Hashtable JDK1.7之HashMap 1. 定义 HashMap实现了Map接口,继承AbstractM ...

  5. MS16-032 windows本地提权

    试用系统:Tested on x32 Win7, x64 Win8, x64 2k12R2 提权powershell脚本: https://github.com/FuzzySecurity/Power ...

  6. LVS之DR模式部署

    一.LVS-DR数据包流向分析 为方便进行原理分析,将Client与群集机器放在同一网络中,数据包流经的路线为1-2-3-41.Client 向目标 VIP 发出请求,Director(负载均衡器)接 ...

  7. Git Best Practice All In One

    Git Best Practice All In One git workflow 本地开发环境: 开发人员自测的,可以是自己本地部署的静态服务器,当然也可类似是运行 npm server类似的环境, ...

  8. styled-components all in one

    styled-components all in one CSS in JS https://www.styled-components.com/ https://github.com/styled- ...

  9. CSS Modules in depth

    CSS Modules in depth https://github.com/css-modules/css-modules https://webpack.js.org/loaders/css-l ...

  10. flutter & dart & vs code & bug

    flutter & dart & vs code & bug Waiting for another flutter command to release the startu ...