zoukankan      html  css  js  c++  java
  • 内存的管理方式

    1、内存的区域

        对于内存的区域划分上,不同的区域划分上都各有不同。

    划分1:

    代码区、堆、栈、 全局区(静态存储区)、 文字常量区、

    划分2:

    代码段、堆、栈、  data段、BSS段、文字常量区

    全局区:

        又成为静态存存储区。保存的是全局变量和静态变量(带有static 关键字)。全局区分为两个区域:一个区域保存的是经过初始化,且初始化的值不为零的全部变量和静态变量;一个区域保存的是没有经过初始化或者初始化的值为零的。程序结束由 OS 进行释放

    常量区:

        将一些不可以被更改的只读的常量进行保存的区域。比如文字字符串等。程序结束之后由系统释放。

    代码区:

        保存的是二进制代码的区域。

    堆:

        由程序猿手动 malloc/free进行开辟的空间,一般也是由程序猿调用 free/delete 进行释放,即使没有进行释放,也可以由 OS 进行释放。

    栈:

        程序运行的时候由编系统进行分配,存在函数的的局部变量等。程序结束由系统自动释放。

    DATA段:

        有经过初始化的全局变量和静态变量存储的区域,当然初始值不能为零

    BSS段:

        保存的是没有经过初始化的全局变量和静态变量存储的区域,或者经过初始化但是初始值为零的也保存在这个区域。

    注意:很显然,DATA 段和 BSS 段的也行,其实就是全局区(静态存储器)内部之一,DATA 段和 BSS 段只不过是全局区更加精细的划分。

    解释:

        借助前人总结的知识:

    int a = 0;            全局初始化区  
    char *p1;          全局未初始化区  
    main()  
    {  
      int b;                          //
      char s[] = "abc";      //
      char *p2;                  //
      char *p3 = "123456";          //"123456/0"在常量区,p3在栈上。   
      static int c =0//全局(静态)初始化区  
      p1 = (char *)malloc(10);  
      p2 = (char *)malloc(20);  
                                                    //分配得来得10和20字节的区域就在堆区。  
      strcpy(p1, "123456");         // 123456 放在常量区,编译器可能会将它与p3所指向的"123456"                              //优化成一个地方。   
    }

    2、内存的三种来源:栈、堆、全局区

    栈:

        (1)运行时候由编译器自动分配自动回收,这一切都是自动的,程序猿不用管理

        (2)反复使用:每一个进程,操作系统都会为这个进程分配栈,这个进程不论是怎么出入栈,都是在这个栈,反复使用。

        (3)脏内存:栈内存由于反复的使用,程序使用完毕之后不会去做清理的工作,所以重新使用栈的时候,值就是脏的。

        (4)临时性:局部变量的出栈入栈,每次都是不一样,所以都是临时性的,所以,绝对不要返回栈变量的指针,因为栈地址都是临时的,

        (5)栈溢出:因为栈的大小是操作系统设定的,当出现无线递归或者出现巨大的局部变量。

    堆:

        (1)大块内存:栈的空间非常有限,所以当需要需要大块内存的时候,就在堆进行申请,

        (2)手动申请、释放: 使用 malloc/new 申请,free/delete 进行释放。

        (3)脏内存 : 堆内存也是被反复使用的

    malloc 实际应用:

        操作系统会对空闲的内存块进行组织管理,而这种组织管理的方式是以链表的形式。当程序猿调用 malloc 的时候就从空闲的链表找出一块大小满足申请要求的空间(可以比用户申请的大),然后将这个内存空间一分为二:一部分是用户申请空间的大小,另外的部分是维护链表这个节点的基本信息(比如地址、块内存的大小)。所以当 malloc 的时候,不论申请的空间是多大,都必须申请一块用于维护链表的空间。

    #include <stdio.h>
    #include<stdlib.h>
    int main(void)
    {
        int i,j;
         FILE * fp = fopen("qxj511.txt", "w");
        for ( i = 0; i < 2048; i++)
        {
            int *p1 = (int *)malloc(i);
            int *p2 = (int *)malloc(i);
    
            fprintf(fp, "i =%d : p1 = %d, p2 = %d,
    ",i, p1, p2);
            free(p1);
            free(p2);        
        }
        fclose(fp); /*关闭文件*/
    }

        在 gcc 的编译器下面做的测试,

    i =0 : p1 = 151765360, p2 = 151765376,    // 1
    i =1 : p1 = 151765376, p2 = 151765360,
    i =2 : p1 = 151765360, p2 = 151765376,
    i =3 : p1 = 151765376, p2 = 151765360,
    i =4 : p1 = 151765360, p2 = 151765376,
    i =5 : p1 = 151765376, p2 = 151765360,
    i =6 : p1 = 151765360, p2 = 151765376,
    i =7 : p1 = 151765376, p2 = 151765360,
    i =8 : p1 = 151765360, p2 = 151765376,
    i =9 : p1 = 151765376, p2 = 151765360,
    i =10 : p1 = 151765360, p2 = 151765376,
    i =11 : p1 = 151765376, p2 = 151765360,
    i =12 : p1 = 151765360, p2 = 151765376, // 1 
    i =13 : p1 = 151765392, p2 = 151765416, // 2
    i =14 : p1 = 151765416, p2 = 151765392,
    i =15 : p1 = 151765392, p2 = 151765416,
    i =16 : p1 = 151765416, p2 = 151765392,
    i =17 : p1 = 151765392, p2 = 151765416,
    i =18 : p1 = 151765416, p2 = 151765392,
    i =19 : p1 = 151765392, p2 = 151765416,
    i =20 : p1 = 151765416, p2 = 151765392,
    i =21 : p1 = 151765440, p2 = 151765472,
    i =22 : p1 = 151765472, p2 = 151765440, // 2
    。。。。。。。

        经过笔者的测试,当 申请的的空间,从零到12个字节的时候,两者的差是16个字节,后序申请的全部的空间差是 8 个字节。也就是说,实际申请的空间是链表头部 + 申请的空间,同时,8 个字节是处于内存对齐。

    参考 : http://blog.csdn.net/misskissc/article/details/17717717

        (1)malloc(0) :

    If size is  0,  thenmalloc()  returns either NULL, or a unique pointer value that can later be successfully passed to free().

    根据官方的解释,当申请的空间为零的时候,返回值要么是为 NULL,要么就可以正确返回一个地址,这个地址被正确释放。但是实际上,都是返回后者。

        根据 malloc 的实现方式,虽然申请的空间为零,但是链表的指针也是会被申请一段空间的,所以可以正确申请,空间为 16 字节(maybe 8字节) + 0; 而这个链表指针地址其实就是 malloc 的返回值的地址。

    注意: 对于链表维护空间的大小是16 字节,这个是不确定的,有人说是8个字节,

    malloc 与 sizeof:

        使用 malloc 是申请了一个程序猿指定的空间,返回值是指向这段空间的的首地址。想要计算这段申请空间的大小,是不可以通过 sizeof 计算出来的:

    int *p = (int *)malloc(10 * sizeof(int));
    printf("%d
    ", sizeof(p));

     

    打印出来:

    等于4

        原因分析,p 是指向申请空间的首地址,也就是说这个是地址,对于指针来说,不论指向的空间是多大,指针占据的就是四个字节。所以,sizeof 是不能计算 malloc。

  • 相关阅读:
    readAsDataURL(file) & readAsText(file, encoding)
    MySQL: Integer & String types
    JavaScript 中事件绑定的三种方式
    vue-router 导航守卫
    js 常见数组算法
    CSS渐变色边框,解决border设置渐变后,border-radius无效的问题
    margin:auto你真的理解么
    当margin和padding的值是百分比时,如何计算
    关于 js 函数参数的this
    Vue.js 中的 v-cloak 指令
  • 原文地址:https://www.cnblogs.com/qxj511/p/4933705.html
Copyright © 2011-2022 走看看