malloc函数实现过程

2022-08-24 09:37:56 浏览数 (1)

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

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

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

代码语言:javascript复制
// 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函数的具体实现过程

代码语言:javascript复制
// 该段代码拷贝于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.cn/140036.html原文链接:https://javaforall.cn

0 人点赞