zoukankan      html  css  js  c++  java
  • C内存管理一 概述

    我们写了这么多年的程序猿。可能理论方面还比不上大学生。有人 "嘘"我了,假设有能回答下面几个问题的同学请举手:
    1.面试常常遇到:同学请说说堆栈的差别?
    2.同学请说说一个函数在堆栈中调用过程(首先要知道函数过程是保存在什么中的)。
    3.静态变量、全局变量、局部变量、常量等哪些是保存在堆中,哪些是栈中。哪些是静态区域中。
    事实上回答第一个我问题,第二和第三问题就是........还真有人举手。就算你举手了,我也要讲。有不正确的地方。这几位同学给我批评指正。

    先来看图:



    就上图来看堆栈差别是.......非常明显堆比栈大。(别嘘),操作系统太高深此处省略,其他还有文字常量区、程序代码区。在其他我也不知道有什么此处省略。

    我们专门来看看 栈、堆、静态存储区。准备好了吗?

    什么是堆,什么是栈

    堆--heap  栈--stack  最大的差别:一个四个字母。一个5个字母。

    宏观上来说。栈是由系统提供的数据结果,而堆是由C/C++函数库提供的。

    从这句话中我的推測理解是栈是系统提供和管理的,而堆是编程语言提供和管理的。在浓缩一下就是栈是自己主动管理的。而堆是手动管理的。

    微观上来说。

    堆栈就是一种方式,一种存储数据的方式或者一种数据结构。

    看它的定义:栈是一种先进后出的线性表,仅仅要符合先进后出的原则的线性表都是栈。

    而堆是一种二叉树,有最大推、最小堆,我们经常使用的什么冒泡、选择等能够用于堆排序。

    总之浓缩一下:

    栈是系统自己主动管理、採用先进后出方式存储数据的存储区域。

    而堆是採用手动管理(malloc 和 free程序中创建、释放)、採用二叉树存储数据的存储区域。(特殊情况除外。比方栈也有动态分配和静态分配)

    栈是一种先进后出的线性表,仅仅要符合先进后出的原则的线性表都是栈。

    综上:栈的特点就是高速、高效、可是因为是机器读写,灵活性相对较弱。堆因为能够手动大小分配,较为灵活、使用面广泛,可是速度没有栈快。


    堆栈差别

    1、分配方式:自己主动、手动
    2、速度、大小、响应速度:栈快、小,堆慢、大
    3、数据存储方式:先进后出、二叉树

    补充说明:静态存储区似乎给忘了,仅仅要记住一点静态存储区是用来存放全局变量和静态变量的。


    程序中哪些是放在堆中、哪些是放到栈中

    1、栈区(stack): 由编译器自己主动分配释放 。存放函数的參数值。局部变量的值等。其操作方式类似于数据结构中的栈。 
     比如,声明在函数中一个局部变量 int b; 系统自己主动在栈中为b开辟空间比如:声明在函数中一个局部变量 int b; 系统自己主动在栈中为b开辟空间
    2、堆区(heap): 一般由程序猿分配释放, 若程序猿不释放,程序结束时可能由OS回收 。
    须要程序猿自己申请。并指明大小,在c中malloc函数 如p1 = (char *)malloc(10); 在C++中用new运算符 如p2 = (char *)malloc(10); 可是注意p1、p2本身是在栈中的。比如:在c中malloc函数 
    p1 = (char *)malloc(10); 
    p1 = (char *)malloc(20); 
    可是注意p1,p2本身是在栈中的。
    到此我的推測----栈中存储的大部分是地址(还有写少许的局部变量值)。
    3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域。 未初始化的全局变量和未初始化的静态变量在相邻的还有一块区域。 (程序结束后有系统释放 ,即生命周期)
    4、文字常量区 —常量字符串就是放在这里的。
    5、程序代码区—存放函数体的二进制代码。

    程序说明:

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

    函数调用过程

    函数调用主要是在栈中进行的:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址。然后是函数的各个參数,在大多数的C编译器中。參数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

    当本次函数调用结束后,局部变量先出栈。然后是參数。最后栈顶指针指向最開始存的地址。也就是主函数中的下一条指令,程序由该点继续执行。



  • 相关阅读:
    spring mvc---web.xml
    javascript:;与javascript:void(0)使用介绍
    JVM的内存区域划分
    获取配置文件内容
    spring获取webapplicationcontext,applicationcontext几种方法详解
    Spring MVC 中 HandlerInterceptorAdapter的使用(拦截器)
    google开发工具指南
    深克隆
    IO优化
    UML类图
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7025889.html
Copyright © 2011-2022 走看看