美文网首页
程序内存分布

程序内存分布

作者: yutz | 来源:发表于2019-02-26 17:47 被阅读0次

    一个程序的运行起来后,其在内存中有5个区域

    1. 程序代码区
      这个很简单,代码要执行,肯定要加载进内存, 我们不必关心。

    2. 文字常量区
      一般我们这样定义一个字符串时,其是在文字常量区的:
      char* s1 = "hello, world";
      char* s2 = "hello, world";
      if(s1 == s2)
      printf("s1和s2指向同一个在文字常量区的字符串");

    这里, s1和s2指向的是同一个字符串

    1. 静态存储区(不会释放,只到程序结束)
      全局变量,静态变量会放在这个区域,事实上,全局变量也是静态的。

    以上1,2,3三个区域的内存在程序起来的时候就开辟好了的。

    1. 栈(}结束被自动释放)
      局部变量就是在栈里的。另外,函数调用时的参数也是在栈里的,这个现在不必关心

    2. 堆(没有被手动销毁,他一直存在,直到程序结束. )
      malloc或new出来的内存就是在堆里的,需要程序员自己管理清除。

    全局(静态)存储区

    分为DATA段和BSS段。DATA段(全局初始化区)存放初始化的全局变量和静态变量;BSS段(全局未初始化区)存放未初始化的全局变量和静态变量。程序运行结束时自动释放。其中BBS段在程序执行之前会被系统自动清0,所以未初始化的全局变量和静态变量在程序执行之前已经为0。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化

    堆和栈的区别:

    1)空间大小:栈的内存空间是连续的,空间大小通常是系统预先规定好的,即栈顶地址和最大空间是确定的;而堆得内存空间是不连续的,由一个记录空间空间的链表负责管理,因此内存空间几乎没有限制,在32位系统下,内存空间大小可达到4G

    2)管理方式:栈由编译器自动分配和释放,而堆需要程序员来手动分配和释放,若忘记delete,容易产生内存泄漏。

    3)生长方向不同:对于栈,他是向着内存地址减小的方向生长的,这也是为什么栈的内存空间是有限的;而堆是向着内存地址增大的方向生长的

    4)碎片问题:由于栈的内存空间是连续的,先进后出的方式保证不会产生零碎的空间;而堆分配方式是每次在空闲链表中遍历到第一个大于申请空间的节点,每次分配的空间大小一般不会正好等于申请的内存大小,频繁的new操作势必会产生大量的空间碎片

    5)分配效率:栈属于机器系统提供的数据结构,计算机会在底层对栈提供支持,出栈进栈由专门的指令执行,因此效率较高。而堆是c/c++函数库提供的,当申请空间时需要按照一定的算法搜索足够大小的内存空间,当没有足够的空间时,还需要额外的处理,因此效率较低。

    使用内存时几点注意事项:

    1)用new和malloc申请内存时,在使用前要检查内存是否分配成功

    char *p=new char[10];
    if(p==NULL)
    return;
    

    2)使用内存之前要进行初始化

    3)在对内存进行操作时,防止越界,如数组操作要注意下标范围

    4)对于动态分配的内存,一定要手动释放,否则程序每运行一次就会丢失一部分内存,造成内存泄漏

    5)防止内存释放后继续使用它,主要有以下三种情况:

    a.程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。

    b.函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。

    c.使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。

    野指针:“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。

    参考博客:
    https://www.cnblogs.com/xiaohuihui-/p/8353774.html
    https://www.cnblogs.com/mrlsx/p/5411874.html

    相关文章

      网友评论

          本文标题:程序内存分布

          本文链接:https://www.haomeiwen.com/subject/fahzyqtx.html