zoukankan      html  css  js  c++  java
  • C中存储分区详解

    一. 在c中分为这几个存储区:栈(stack),堆(heap),代码段(text),数据段(data),bss 段,常量存储区,
    1.栈(stack):由编译器自动分配释放
    自动分配,自动回收:栈区里面存放的是局部变量;在定义局部变量的时候,系统在栈区自动分配内存,在结束时,自动回收内存;
    脏内存:栈区每次使用之前需要对栈区进行初始化;对于定义局部变量时,需要对局部变量进行初始化;
    临时性:(函数不能返回栈变量的指针,因为这个空间是临时的)
    反复使用:栈内存在程序中其实就是那一块空间,程序反复使用这一块空间。
    栈的大小有限,因此 会出现栈溢出

    2.堆(heap): 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
    手动分配:malloc分配内存,free进行释放内存;
    脏内存:堆区每次使用之前呢需要对堆区进行初始化;
    临时性:堆区每次分配的内存释放之后,就不能在使用;
    malloc的使用:malloc每次分配的内存之后需要进行对其返回指针为void *类型,需要进行强制类型转换,并对返回指针进行检查是否为null;
    malloc和free为c语言的标准库函数,不能分配对象;
    内存泄漏;
    gcc中的malloc默认最小是以16B为分配单元的;如果malloc小于16B的大小时都会返 回一个16字节的大小的内存。

    3.代码段(text):

      也叫文本段,代码段其实就是函数编译后生成的东西;

    4.数据段(data):

      也被称为数据区、静态数据区、静态区;
    c语言中
    1.显示初始化为非零全局变量
    2.显示初始化为非零的静态局部变量存储在这个段;

    5.bss 段(又叫:ZI(zero initial)段):.bss 段
    c语言中
    1).显示初始化为0的全局变量;

    2).未初始化的全局变量存储在这个段。--零初始化段;

    3).显示初始化为0的static局部变量;

    4).未初始化的static局部变量存储在这个段;

    6.自定义段:

      段名由程序员自己定义,段的属性和特征也由程序员自己定义。

    7.常量存储区:

      一块比较特殊的存储区,存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改)

    8.文件映射区:

      进程打开了文件后,将这个文件的内容从硬盘读到进程的文件映射区,以后就直接在内存中操作这个 文件,读写完了后在保存时再将内存中的文件写到硬盘中去。

    9.内核映射区:

      内核映射区就是将操作系统内核程序映射到这个区域了。

    10.不同的存储方式有不同的特点,简单总结如下:
    1)函数内部临时使用,出了函数不会用到,就定义局部变量
    2)堆内存和数据段几乎拥有完全相同的属性,大部分时候是可以完全替换的。

      生命周期不一样:

        堆内存的生命周期是从malloc开始到free结束;

        全局变量是从整个程序一开始执行就开始,直到整个程序结束才会消灭,伴随程序运行的一生。

      启示:如果变量只是在程序的一个阶段有用,用完就不用了,就适合用堆内存;

         如果这个变量本身和程序是一生相伴的,那就适合用全局变量。

    补充1:
    1)所有未初始化的静态(static)变量和全局变量,编译器会默认赋初值0。
    2)程序在加载到内存前,代码区(text)和全局区(data和bss)的大小就是固定的,程序运行期间不能改变。
    3)data段和bss区中的数据的生存周期为整个程序运行过程。
    4)data段、text区和bss区是由编译器在编译时分配的,堆和栈是由系统在运行时分配的。

    12.生命周期/作用域:
    1).生命周期:指变量活着或者说是存在的时间;
    2).作用域:指可以使用这个变量的范围;

    结合示例详解:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    int c = 1;              //初始化为非零的全局变量:.data段
    int a = 0;           //初始化为0的全局变量:.bss段
    char *p1;             //未初始化的全局变量:.bss段
    void main()
    {
      int b;            //局部变量:stack(栈)
      char s[] = "abc";      //局部变量:stack(栈)
      char *p2;           //局部变量:stack(栈)
      char *p3 = "123456";    //字符串"123456"在常量区,p3局部变量:stack(栈)
      static int c = 0;      //显示初始化的局部变量:.bss段
      p1 = (char *)malloc(10);  //malloc分配的内存:heap(堆)
      strcpy(p1, "123456");
    
      system("pause");
      return;
    }

    补充2:

    明确区分堆与栈:
    在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。
    首先,我们举一个例子:

    void func()
    { 
    int* p=new int[5];    //包含了堆与栈
    }

    new分配了一块堆内存;
    局部变量指针变量p分配的是一块栈内存;
    意义:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中。

  • 相关阅读:
    Azure PowerShell (7) 使用CSV文件批量设置Virtual Machine Endpoint
    Windows Azure Cloud Service (39) 如何将现有Web应用迁移到Azure PaaS平台
    Azure China (7) 使用WebMetrix将Web Site发布至Azure China
    Microsoft Azure News(4) Azure新D系列虚拟机上线
    Windows Azure Cloud Service (38) 微软IaaS与PaaS比较
    Windows Azure Cloud Service (37) 浅谈Cloud Service
    Azure PowerShell (6) 设置单个Virtual Machine Endpoint
    Azure PowerShell (5) 使用Azure PowerShell创建简单的Azure虚拟机和Linux虚拟机
    功能代码(1)---通过Jquery来处理复选框
    案例1.用Ajax实现用户名的校验
  • 原文地址:https://www.cnblogs.com/weiyouqing/p/9073420.html
Copyright © 2011-2022 走看看