zoukankan      html  css  js  c++  java
  • free如何知道释放内存长度:vs与glibc分配内存时编译器内部处理

    鉴于网上这个资料实在太少,将以前整理过却未完全的一篇文章贴出来,希望大牛指正vs下内存管理方式。可联系gaoshiqiang1987@163.com

    • vs分配内存
    vs没有源码,编译器在分配内存时,分配给用户的地址减去16个字节(注1),保存了分配内存的类型与大小
    如下表示了vs编译器在分配内存时编译器的处理,代码如下:
     1 int _tmain(int argc, _TCHAR* argv[])
     2 {
     3     char *pcMem = (char *)malloc(8);
     4     short *psMem = (short *)malloc(12);
     5     int *piMem = (int *)malloc(16);
     6     long *plMem = (long *)malloc(20);
     7     float *pfMem  = (float*)malloc(32);
     8     double *pdMem = (double*)malloc(48);
     9 
    10     system("PAUSE");
    11     return 0;
    12 }
    vs2008本地断点调试运行,对应地址分配如下
    pcMem    0x007722c8 "屯屯屯屯������铪铪"    char *
    psMem    0x00772310    short *
    piMem    0x00772358    int *
    plMem    0x007723a8    long *
    pfMem    0x00779230    float *
    pdMem    0x00779290    double *
    如下为pChar减去16个字节的地址内容
    0x007722B8  08 00 00 00 01 00 00 00 7a 00 00 00 fd fd fd fd cd cd cd cd cd cd cd cd fd fd fd fd ab ab ab ab
    0x00772300  0c 00 00 00 01 00 00 00 7b 00 00 00 fd fd fd fd cd cd cd cd cd cd cd cd cd cd cd cd fd fd fd fd
    0x00772348  10 00 00 00 01 00 00 00 7c 00 00 00 fd fd fd fd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
    0x00772398  14 00 00 00 01 00 00 00 7d 00 00 00 fd fd fd fd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
    0x00779220  20 00 00 00 01 00 00 00 7e 00 00 00 fd fd fd fd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
    0x00779280  30 00 00 00 01 00 00 00 7f 00 00 00 fd fd fd fd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
    从上面可以总结以下几点:
    【1】第一顺序的四个字节代表分配内存大小,并以小端(可能跟cpu有关,没在大端机器上验证,欢迎有大端机器的朋友验证)方式呈现,在32位处理器或者32位操作系统下,程序所能允许分配最大内存为2^32次幂;
    【2】第二顺序的四个字节不清楚代表什么
    【3】第三顺序的四个字节代表分配数据类型(注2
    7a--char
    7b--short
    7c--int
    7d--long
    7e--float
    7f--double

    至于还有结构体以及类的分配可能需要另外讨论

    【4】第四顺序的四个字节都为fd,猜测默认为保留字节
    对应不同结构体类型亦有不同值与之对应
    疑问:如何从上面的资料计算申请分配内存的大小
    我们知道了所分配内存个数在第一顺序的四个字节中有体现,但是所分配内存的单个单元大小几何单从第三顺序的四个字节看不出所以然。再分析下第三顺序的四个字节,对应【总结3】,略加分析,会发现单个单元大小也对应了某个值。我试了下不同结构体对应的值也各不一样。猜测vs编译器对其单个单元值在编译时进行了计算,以便于在释放内存时清楚该释放内存大小。
     
    • glibc分配内存
    glibc则清晰很多,因为可以阅读源码,其在分配内存前增加了一个 HEADER_SIZE ,跟踪malloc函数实现可以发现
    typedef struct header {
      long check;
      union {
        struct header *next;
        struct free_list *fl;
      } u;
    } *header_t;
     
    #define HEADER_SIZE sizeof (struct header)
     
    typedef struct free_list {
     spin_lock_t lock; /* spin lock for mutual exclusion */
     header_t head; /* head of free list for this size */
    #ifdef DEBUG
     int in_use; /* # mallocs - # frees */
    #endif /* DEBUG */
    } *free_list_t;

    注1:这里写16byte是因为对比了分配内存首地址往前偏移8byte、16byte、32byte,发现16byte内存内容跟所分配的最接近,因为没有源码,所以只能做如上猜测

    注2:没有实际资料证明,只是猜想,上面几个是基本数据类型,但是面对结构体或者类时其怎么表示尚不清楚

  • 相关阅读:
    C# WebClient 使用http免费代理
    C#中给WebClient添加代理Proxy
    浅谈C#实现Web代理服务器的几大步骤
    Visual Studio 2017各版本安装包离线下载、安装全解析
    C# HttpClient, 使用C#操作Web
    ROS学习之 tab补全错误
    ROS学习之group标签
    ROS学习之CMakeLists.txt
    ROS学习之包的概念
    ROS学习之package.xml
  • 原文地址:https://www.cnblogs.com/littlejohnny/p/4846361.html
Copyright © 2011-2022 走看看