malloc函数实现过程

malloc函数实现过程在C语言中,要进行动态内存的开辟就需要使用到malloc函数,在C++中使用的new关键字的基层也是调用了malloc函数,可见malloc函数的重要性,这个就浅析一下malloc的实现过程。本文的测试环境是win10+vs2015。首先先看看malloc函数怎么去调用//malloc函数原型//void*malloc(size_tsize);//(MSDN中的定义)type

大家好,又见面了,我是你们的朋友全栈君。

在C语言中,要进行动态内存的开辟就需要使用到malloc函数,在C++中使用的new关键字的基层也是调用了malloc函数,可见malloc函数的重要性,这个就浅析一下malloc的实现过程。
本文的测试环境是win10+vs2015。

首先先看看malloc函数怎么去调用

// malloc函数原型
// void *malloc( size_t size );//(MSDN中的定义)
type* temp=(type*)malloc(sizeof(type*n));
// type表示数据类型;
// n表示需要创建几个该类型的成员
// sizeof(type*n)表示成员所占空间

有函数原型可知

  • malloc函数返回值是void*,所以实际上是用的时候都将其进行了强制转换
  • malloc函数的传参是size_t类型的,在vs2015中的定义是
    typedef unsigned int size_t;
    表示它是无符号整数类型
    sizeof关键返回值是size_t,所以不会冲突

重点内容
malloc函数申请空间的操作步骤:

  1. 对堆进行加锁
  2. 在正式申请空间之前,对堆进行校验
  3. 检测申请内存块的类型
  4. 检测内存空间是否充足,不够设置错误信息,返回NULL,否则进行5
  5. 检测块的类型
  6. 计算本次所要申请的内存块的总字节数
  7. 按照计算的总字节数申请内存,底层真正向堆申请空间的是HeapAlloc函数
  8. 检测是否申请成功,如果申请失败设置错误信息,返回NULL,否则执行9
  9. 修改请求次数和目前申请的总字节数
  10. 将新申请的内存块的新节点头插到双向链表中
  11. 给该结点对应的结构体赋值
  12. 填充空间
  13. 获取申请内存块中存放有效数据的真正位置
  14. 对堆进行解锁
  15. 返回有效数据区域的地址

malloc函数的具体实现过程

// 该段代码拷贝于vs2015的malloc.h
// malloc.h
#pragma once
#define _INC_MALLOC

#include <corecrt.h>
#include <corecrt_malloc.h>

_CRT_BEGIN_C_HEADER

// 查看是win32还是win64的平台

#ifdef _WIN64
    #define _HEAP_MAXREQ 0xFFFFFFFFFFFFFFE0
#else
    #define _HEAP_MAXREQ 0xFFFFFFE0
#endif

// 定义相关的宏常量
#define _HEAPEMPTY (-1)//堆空
#define _HEAPOK (-2)
#define _HEAPBADBEGIN (-3)
#define _HEAPBADNODE (-4)
#define _HEAPEND (-5)//堆尾
#define _HEAPBADPTR (-6)
#define _FREEENTRY 0
#define _USEDENTRY 1

//定义一个结构体
typedef struct _heapinfo
{
    int* _pentry;
    size_t _size;
    int _useflag;
} _HEAPINFO;

//定义相关宏
#define _mm_free(a) _aligned_free(a)
#define _mm_malloc(a, b) _aligned_malloc(a, b)

// 未完待续。。。

_Ret_notnull_ _Post_writable_byte_size_(_Size)
void* __cdecl _alloca(_In_ size_t _Size);



#if !defined __midl && !defined RC_INVOKED

    _ACRTIMP intptr_t __cdecl _get_heap_handle(void);

    _Check_return_
    _DCRTIMP int __cdecl _heapmin(void);

    #if defined _DEBUG || defined _CRT_USE_WINAPI_FAMILY_DESKTOP_APP || defined _CORECRT_BUILD
        _ACRTIMP int __cdecl _heapwalk(_Inout_ _HEAPINFO* _EntryInfo);
    #endif

    #ifdef _CRT_USE_WINAPI_FAMILY_DESKTOP_APP
        _Check_return_ _DCRTIMP int __cdecl _heapchk(void);
        _DCRTIMP int __cdecl _resetstkoflw(void);
    #endif

    #define _ALLOCA_S_THRESHOLD 1024
    #define _ALLOCA_S_STACK_MARKER 0xCCCC
    #define _ALLOCA_S_HEAP_MARKER 0xDDDD

    #ifdef _WIN64
        #define _ALLOCA_S_MARKER_SIZE 16
    #else
        #define _ALLOCA_S_MARKER_SIZE 8
    #endif

    _STATIC_ASSERT(sizeof(unsigned int) <= _ALLOCA_S_MARKER_SIZE);


    #pragma warning(push)
    #pragma warning(disable:6540)

    __inline void* _MarkAllocaS(_Out_opt_ __crt_typefix(unsigned int*) void* _Ptr, unsigned int _Marker)
    {
        if (_Ptr)
        {
            *((unsigned int*)_Ptr) = _Marker;
            _Ptr = (char*)_Ptr + _ALLOCA_S_MARKER_SIZE;
        }
        return _Ptr;
    }

    __inline size_t _MallocaComputeSize(size_t _Size)
    {
        size_t _MarkedSize = _Size + _ALLOCA_S_MARKER_SIZE;
        return _MarkedSize > _Size ? _MarkedSize : 0;
    }

    #pragma warning(pop)

#endif



#ifdef _DEBUG

    #ifndef _CRTDBG_MAP_ALLOC
        #undef _malloca
        #define _malloca(size) \
            __pragma(warning(suppress: 6255 6386))                                       \
            (_MallocaComputeSize(size) != 0                                              \
                ? _MarkAllocaS(malloc(_MallocaComputeSize(size)), _ALLOCA_S_HEAP_MARKER) \
                : NULL)
    #endif

#else

    #undef _malloca
    #define _malloca(size) \
        __pragma(warning(suppress: 6255 6386))                                             \
        (_MallocaComputeSize(size) != 0                                                    \
            ? (((_MallocaComputeSize(size) <= _ALLOCA_S_THRESHOLD)                         \
                ? _MarkAllocaS(_alloca(_MallocaComputeSize(size)), _ALLOCA_S_STACK_MARKER) \
                : _MarkAllocaS(malloc(_MallocaComputeSize(size)), _ALLOCA_S_HEAP_MARKER))) \
            : NULL)

#endif



#if defined __midl && !defined RC_INVOKED
#elif defined _DEBUG && defined _CRTDBG_MAP_ALLOC
#else

    #undef _freea

    #pragma warning(push)
    #pragma warning(disable: 6014)
    __inline void __CRTDECL _freea(_Pre_maybenull_ _Post_invalid_ void* _Memory)
    {
        unsigned int _Marker;
        if (_Memory)
        {
            _Memory = (char*)_Memory - _ALLOCA_S_MARKER_SIZE;
            _Marker = *(unsigned int*)_Memory;
            if (_Marker == _ALLOCA_S_HEAP_MARKER)
            {
                free(_Memory);
            }
            #ifdef _ASSERTE
            else if (_Marker != _ALLOCA_S_STACK_MARKER)
            {
                _ASSERTE(("Corrupted pointer passed to _freea", 0));
            }
            #endif
        }
    }
    #pragma warning(pop)

#endif



#if !__STDC__
    #define alloca _alloca
#endif



_CRT_END_C_HEADER
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140036.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • win11 修改host文件[通俗易懂]

    win11 修改host文件[通俗易懂]转到“开始”菜单搜索栏,输入“记事本”,然后以管理员身份运行记事本。单击文件并从菜单中选择“打开…”选项。在“文件名:”选项中输入主机文件地址(C:\Windows\System32\drivers\etc\hosts),然后单击“打开”。选择打开所有文件可以看到host文件在您的记事本上打开Host文件,然后您可以从这里对其进行编辑。输入IP地址和域名以配置映射。保存修改注意查看保存的文件类型为所有文件提示替换同意之后退出完成修改…

    2022年10月12日
    2
  • 常见免费邮箱 SMTP 服务地址及端口「建议收藏」

    常见免费邮箱 SMTP 服务地址及端口「建议收藏」常见免费邮箱SMTP服务地址及端口邮箱服务服务器地址SSL端口号非SSL端口号163邮箱IMAPimap.163.com993143SMTPsmtp.163.com465/99425POP3pop.163.com995110QQ邮箱IMAPimap.qq.com993143SMTPsmtp.qq.com465/58725POP3pop.qq.com995–foxmail邮箱IMAPimap

    2022年9月27日
    2
  • 让电脑报废的代码(30万行代码)

    作者:小傅哥博客:https://bugstack.cn沉淀、分享、成长,让自己和他人都能有所收获!????一、前言20万行代码写完,毕业了找一份工作不是问题!刚一毕业因为找不到工作,就得报名去参加Java培训的大有人在。并不是说参加培训就不好,只不过以你现在这个毕业的时间点参加,就会显得特别匆忙。因为你的压力既来自于培训还需要花家里一笔不小的费用,也有同班同学已经找到一份不错的工作开始赚钱的比对。大学四年其实有足够的时间让你学会编程,也能从一个较长时间的学习中,知道自己适合不适合做程序员。

    2022年4月11日
    215
  • pytest的使用_java中方法的调用

    pytest的使用_java中方法的调用Pytest执行用例规则Pytest在命令行中支持多种方式来运行和选择测试用例1.对某个目录下所有的用例pytest2.对模块中进行测试pytesttest_mod.py3.对文件夹进行

    2022年7月30日
    5
  • datagrip2021激活码【中文破解版】

    (datagrip2021激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月27日
    107
  • js 删除对象里的某个属性[通俗易懂]

    删除属性有很多方法,学到了就在这里记录一下。有一个对象a。有2个属性b=1,c=2删除b,保留c1.使用deleteleta={b:1,c:2}deletea.b//trueconsole.log(a)//{c:2}2.使用解构leta={b:1,c:2}let{b,…a}=aconsole.log(a)//{c:2}…

    2022年4月11日
    53

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号