zoukankan      html  css  js  c++  java
  • 内存四区、野指针以及堆栈的区别

    C语言内存四区:代码区、数据区、栈区、堆区
    1.代码区(.text):代码区中主要存放程序中的代码(二进制),属性是只读。
     
    2.数据区(静态存储区):主要包括静态全局区和常量区,如果要站在汇编角度细分的话还可以分为很多小的区。
          A.全局区(静态区,static):全局变量和静态变量的存储是放在一块的,初始化的(全局变量和静态变量)在一块区域(.data,显示初始化为非零的全局变量), 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(.bss,显式初始化为0或者并未显式初始化)。 程序结束后有系统释放。
         B.常量区 :常量字符串就是放在这里的。(常量、函数名、关键字、字符串等) 程序结束后由系统释放。
     
    3.栈区(stack):内存的分配和释放都是自动进行 ,存放函数的参数值,局部变量的值等。栈内存分配运算内置于处理器的指令集中,效率高,但容量有限,局部变量生命周期短。(linux中查看栈大小,ulimit -s,本机8M)
     
    4.堆区(heap):有些操作对象只有在程序运行时才能确定,这样编译器在编译时无法为他们预先分配内存空间,只有在程序运行时分配,所以称为动态内存,malloc/free等。

    程序的运行:

     1 双击运行程序时,操作系统把硬盘上的程序load到内存。

     2 操作系统把c代码分成四个区。

       3 操作系统找到入口函数main,开始执行。

    动态内存的申请和释放
    #include <stdlib.h>
    void *malloc(size_t size);
    malloc工作机制:
        malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表(堆内存)。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
     
    1.只关心申请内存的大小,单位字节。
    2.申请空间一定是连续的。有可能申请到比实际申请的大,申请失败时返回空指针。
    3.需要将申请的内存用一个指针来接住。
    4.需要显示初始化。堆区是不会在自动的分配时做初始化的,包括清零。
     
    #include <stdlib.h> 
    void free(void *ptr);
      
      1.必须提供初始地址,否则会出现内存泄漏的现象。
      2.malloc和free配对使用,避免内存泄露。
      3.不允许重复释放,因为该空间可能再第一次释放后被分配利用了。
      4.free只能释放堆空间,其他都执行错误。
     
    关于野指针
    所谓野指针是垃圾指针,不是NULL指针。导致的主要原因如下:
      1.指针变量没有初始化。
      2.指针被free释放后,没有置NULL。free是把指针所指向的内存空间释放,使内存成为自由内存。而指针仍然指向这块自由内存,很危险。
      3.指针操作超越了变量的作用范围。
      4.不要返回指向栈内存的指针。
     
    堆和栈的区别
    1.申请方式
      栈(stack):系统自动分配,如int b;
      堆(heap):程序员手动分配,如malloc
     
    2.申请后的系统响应
      栈(stack):栈空间剩余内存大于申请空间,才会申请成功,否则报错。
      堆(heap):在系统中有一个记录空闲内存地址的链表。当系统收到申请时,系统就会开始遍历链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,将该节点的空间分配给程序。另外,对于多数系统,会在这块内存空间的首地址处记录本次分配的大小。这样,代码中的删除的语句才能正确释放本内存空间。如果找到的堆节点的大小与申请的大小不同,系统会自动的将多余的那部分重新装入空闲链表中。
     
    3.申请大小的限制。
      栈(stack):栈是向低地址扩展的数据结构,是一块连续的内存区域。栈的容量和起始地址都是系统预先设置好的,申请过大的内存会导致栈溢出,因此,能获取的空间比较小(在Linux version 3.2.0-87-generic-pae中栈的大小为8M)
      堆(heap):堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统采用链表来存储空闲的内存地址,地址是不连续的,而链表遍历的方向是由低地址向高地址。堆的大小也受限于有效的虚拟内存,因此获取空间比较灵活,也比较大。
     
    4.申请速度的限制
      栈(stack):由系统自动分配,速度比较快,但程序员一般无法控制。
      堆(heap):由malloc等分配,一般速度比较慢,而且容易产生内存碎片,不过使用方便。
     
    5.堆和栈中的存储内容
      栈(stack):在调用函数的时候,第一个进栈的是函数调用语句的下一条可执行语句的地址,然后是函数的各个参数,一般情况,参数由右往左入栈的,然后是函数中的局部变量。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始的存储地址,也就是调用该函数出的下一条指令,程序由该点继续运行。
      堆(heap):一般在堆的头部用一个字节存放堆的大小,堆中的具体内容由程序员安排。
     
     
  • 相关阅读:
    Java+7入门经典 -1 简介
    优化算法动画演示Alec Radford's animations for optimization algorithms
    如何写科技论文How to write a technical paper
    开始学习深度学习和循环神经网络Some starting points for deep learning and RNNs
    用500行Julia代码开始深度学习之旅 Beginning deep learning with 500 lines of Julia
    用10张图来看机器学习Machine learning in 10 pictures
    ICLR 2013 International Conference on Learning Representations深度学习论文papers
    ICLR 2014 International Conference on Learning Representations深度学习论文papers
    卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现
    卷积神经网络Convolutional Neural Networks
  • 原文地址:https://www.cnblogs.com/still-smile/p/11646090.html
Copyright © 2011-2022 走看看